ส่วนย่อยไม่ได้ถูกแทนที่ แต่วางไว้ด้านบนของชิ้นส่วนก่อนหน้า


105

กิจกรรม:

FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();

Fragment1 fragment = new Fragment1();
Fragment2 fragment2 = new Fragment2();

transaction.replace(R.id.Fragment1, fragment);
transaction.addToBackStack(null);
transaction.commit();

FragmentTransaction transaction2 = getSupportFragmentManager().beginTransaction();
transaction2.replace(R.id.Fragment1, fragment2);
transaction2.addToBackStack(null);
transaction2.commit();

รหัสในมุมมอง:

<fragment
    android:id="@+id/Fragment1"
    android:name="com.landa.fragment.Fragment1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true"
    android:layout_alignParentLeft="true"
    android:layout_below="@+id/include1" /> 

ปัญหาคือเนื้อหาไม่ได้ถูกแทนที่จริงๆ - มันถูกวางไว้ด้านบน (มันจึงทับซ้อนกัน)

เมื่อฉันคลิกย้อนกลับส่วนแรกจะแสดงอย่างถูกต้อง (โดยไม่มีส่วนที่สอง) แต่ในตอนแรกทั้งสองจะมองเห็นได้ (ฉันต้องการให้มองเห็นเฉพาะชิ้นสุดท้ายเท่านั้น)

ฉันขาดอะไรไปที่นี่?


ในกรณีของฉันปัญหาเกิดจากการที่ฉันไม่ได้ใช้ id ที่เหมาะสมของมุมมองคอนเทนเนอร์นั่นคือฉันไม่ได้ส่งผ่านค่าที่ถูกต้องcontainerViewId(ในreplaceวิธีการ)
nbro

คำตอบ:


145

คุณทำผิดสองอย่างที่นี่:

  1. คุณไม่สามารถแทนที่แฟรกเมนต์ที่วางแบบคงที่ในxmlไฟล์เค้าโครง คุณควรสร้างภาชนะ (เช่นFrameLayout) ในรูปแบบแล้วเพิ่มชิ้น programatically FragmentTransactionใช้

  2. FragmentTransaction.replaceคาดว่า id ของคอนเทนเนอร์ที่มีแฟรกเมนต์ไม่ใช่ id ของแฟรกเมนต์เป็นพารามิเตอร์แรก ดังนั้นคุณควรส่งอาร์กิวเมนต์แรกเป็น id ของคอนเทนเนอร์ที่คุณเพิ่มส่วนแรกไป

คุณสามารถอ้างอิงลิงค์นี้เพื่อดูรายละเอียดเพิ่มเติม


17
ใช้เป็นภาชนะจะดีกว่าการใช้FrameLayout LinearLayout
Marcel Bro

3
การใช้ FrameLayout ที่ว่างเปล่าในกิจกรรมก็ช่วยแก้ปัญหาของฉันได้เช่นกัน
Subtle Fox

1
ได้ผลเมื่อทำเช่นนี้ แต่แล้วเมื่อฉันเริ่มแอปพลิเคชันและกดปุ่มย้อนกลับทันทีฉันจะอยู่ในสถานะที่ส่วนว่างเปล่าแทนที่จะออกจากแอป?
MasterScrat

@MasterScrat ละเว้นaddTobackStack(..)เมื่อทำธุรกรรมครั้งแรก วิธีนี้จะหลีกเลี่ยงการวางคอนเทนเนอร์ FrameLayout ที่ว่างเปล่าลงบนกองหลัง คุณจะยังคงสามารถกลับไปที่ส่วนที่คุณเพิ่มได้
Alex Meuer

นี่คือวิดีโอที่ยอดเยี่ยมที่แสดงให้เห็นถึงคำอธิบายของคุณ youtube.com/watch?v=EbcdMxAIr54
SQL และ Java Learner

32

ผมมีปัญหาที่คล้ายกัน แต่ปัญหาของฉันคือการที่ผมใช้สองผู้จัดการส่วนที่แตกต่างกัน: หนึ่งจากและหนึ่งจากgetSupportFragmentManager() getFragmentManager()หากฉันเพิ่มหนึ่งส่วนด้วยSupportFragmentManagerและจากนั้นลองแทนที่ส่วนด้วยส่วนFragmentManagerนั้นส่วนจะถูกเพิ่มที่ด้านบน ฉันจำเป็นต้องเปลี่ยนรหัสเพื่อให้ใช้รหัสเดียวกันFragmentManagerนี้ได้และช่วยแก้ไขปัญหาได้


17

ไซต์นักพัฒนา Android แนะนำให้ใช้ a FrameLayoutเพื่อโหลดชิ้นส่วนแบบไดนามิกในเวลาทำงาน คุณได้ฮาร์ดโค้ดแฟรกเมนต์ในไฟล์ xml ของคุณ ดังนั้นจึงไม่สามารถลบออกได้ในขณะทำงานตามที่ระบุไว้ในลิงค์นี้:

http://developer.android.com/training/basics/fragments/creating.html

ลิงค์นี้แสดงวิธีการเพิ่มชิ้นส่วนผ่านโปรแกรมของคุณ:

http://developer.android.com/training/basics/fragments/fragment-ui.html


7

ฉันมีปัญหาเดียวกันและเห็นคำตอบทั้งหมด แต่ไม่มีข้อผิดพลาดของฉัน! ก่อนที่จะพยายามแทนที่ส่วนปัจจุบันฉันได้แสดงส่วนเริ่มต้นใน xml ของกิจกรรมคอนเทนเนอร์ดังนี้:

<FrameLayout
    android:id="@+id/fragment_frame_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <fragment
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:name="....ShopFragment"
        android:id="@+id/fragment"
        tools:layout="@layout/fragment_shop" />
</FrameLayout>

หลังจากนั้นแม้ว่าฉันจะผ่านFrameLayoutไปfragmentTransaction.replace()แต่ฉันก็มีปัญหาแน่นอน มันกำลังแสดงส่วนที่สองอยู่ด้านบนของส่วนก่อนหน้า

ปัญหาได้รับการแก้ไขโดยการลบส่วนออกจาก xml และแสดงโดยทางโปรแกรมในonCreate()วิธีการของกิจกรรมคอนเทนเนอร์สำหรับการแสดงตัวอย่างเริ่มต้นเมื่อเริ่มต้นโปรแกรมดังนี้:

    fragmentTransaction = getFragmentManager().beginTransaction();
    fragmentTransaction.replace(R.id.fragment_frame_layout,new ShopFragment());
    fragmentTransaction.addToBackStack(null);
    fragmentTransaction.commit();

และกิจกรรมคอนเทนเนอร์ xml:

<FrameLayout
    android:id="@+id/fragment_frame_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

4

คุณสามารถล้าง backStack ก่อนที่จะเปลี่ยนชิ้นส่วน:

    FragmentManager fm = getActivity().getSupportFragmentManager();

    for (int i = 0; i < fm.getBackStackEntryCount(); i++) {
        fm.popBackStack();
    }

    // replace your fragments

ปัญหาคือเขาได้ประกาศแฟรกเมนต์ในไฟล์เลย์เอาต์ xml ของเขา ดังนั้นจึงไม่สามารถถอด / เปลี่ยนได้ในขณะทำงาน
Poonam Anthony

สิ่งนี้ใช้ได้ผลสำหรับฉันการพยายามแทนที่ชิ้นส่วนโดยไม่ต้องล้างแบ็คสแต็กดูเหมือนว่าจะปล่อยให้รายการแบ็คสแต็กล่าสุดอยู่ด้านบนของส่วนอื่น ๆ
speedynomads

3
<FrameLayout
    android:id="@+id/fragment_frame_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="?android:windowBackground">
//Add fragment here
</FrameLayout>

เพิ่มandroid:background="?android:windowBackground">ลงในคอนเทนเนอร์ที่ส่วนของคุณอาศัยอยู่ ในกรณีของฉันฉันเพิ่ม a FrameLayoutซึ่งน่าจะช่วยได้


1

ใช้ภาชนะแทนการใช้ชิ้นส่วน

<FrameLayout
        android:id="@+id/container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="Hello World!" />

ตอนนี้อยู่ใน MainActivity

if(condition)
    getFragmentManager().beginTransaction().replace(R.id.container,new FirstFragment()).commit();                    
else
    getFragmentManager().beginTransaction().replace(R.id.container, new SecondFragment()).commit();

โปรดทราบว่าคลาสแฟรกเมนต์ของคุณควรนำเข้า 'android.app.Fragment' ตรวจสอบให้แน่ใจว่าคุณใช้การใช้งาน "support.v4" หรือ "ดั้งเดิม" และอย่าผสมเข้าด้วยกัน ฉันได้รับปัญหานี้เพราะฉันผสมมันเข้าไป


0

ฉันเห็นด้วยกับคำตอบของ Sapan Diwakar แต่ฉันพบวิธีแก้ปัญหาเกี่ยวกับวิธีการทำเช่นนี้

อันดับแรกในกิจกรรมของคุณ (เช่น activity_main ) ที่คุณมีเลย์เอาต์ทั้งหมดให้เพิ่ม a FrameLayout. match parentความสูงของมันและความกว้างที่ควรจะเป็น นอกจากนี้ให้มันid.

ตอนนี้ในส่วนของคุณซึ่งจะแทนที่เค้าโครงปัจจุบันให้เรียกonPause()และonResume(). เริ่มต้นคอนเทนเนอร์ด้านในViewทั้งหมดใน และตั้งค่าvisibilityเป็นGONEในonResume()และในVISIBLEonPause()

หมายเหตุ : ไม่ใช่สิ่งFrameLayoutที่คุณกำลังแทนที่ด้วยส่วนนี้

สมมติว่าคุณมีViewPager, TabLayout, ImageViewและกำหนดเอง<fragment>activity_main.xmlใน เพิ่มFrameLayoutตามที่กล่าวไว้ข้างต้น

ในabcFragment.javaในonClick()ฟังก์ชั่นเพิ่มaddToBackstack(null)transactionใน

รหัสตัวอย่าง:

ใน xyzFragment ซึ่งจะแทนที่ abcFragment (และทุกอย่างที่แสดงใน activity_main.xml) ให้ทำสิ่งนี้

@Override
    public void onResume() {
        super.onResume();

    // On resume, make everything in activity_main invisible except this fragment.
    slidingTabs = getActivity().findViewById(R.id.sliding_tabs);
    viewPager = getActivity().findViewById(R.id.pager);
    miniPlayerFragment = getActivity().findViewById(R.id.mini_pager);

    slidingTabs.setVisibility(View.GONE);
    viewPager.setVisibility(View.GONE);
    miniPlayerFragment.setVisibility(View.GONE);
}

@Override
public void onPause() {
    super.onPause();

    // Make everything visible again
    slidingTabs = getActivity().findViewById(R.id.sliding_tabs);
    viewPager = getActivity().findViewById(R.id.pager);
    miniPlayerFragment = getActivity().findViewById(R.id.mini_pager);

    slidingTabs.setVisibility(View.VISIBLE);
    viewPager.setVisibility(View.VISIBLE);
    miniPlayerFragment.setVisibility(View.VISIBLE);
}

ขอให้สนุกกับการเขียนโค้ด!


0

คุณสามารถใช้เมธอด setTransition จาก FragmentTransaction เพื่อแก้ไขปัญหาที่ทับซ้อนกัน

transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);

0

ใน Oncreate ()

  BaseFragmentloginpage fragment = new BaseFragmentloginpage();
            android.support.v4.app.FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
            fragmentTransaction.replace(R.id.frame, fragment);
            fragmentTransaction.isAddToBackStackAllowed();
            fragmentTransaction.commit();

ตอนนี้นี่จะเป็นแฟรกเมนต์เริ่มต้นของคุณเสมอ ... ถ้าคุณเพิ่มแฟรกเมนต์ในเลย์เอาต์ xml มันจะทับซ้อนกันเสมอดังนั้นตั้งค่าเนื้อหาเริ่มต้นด้วยแฟรกเมนต์ในขณะรัน


0

ฉันมีปัญหาเดียวกันหลังจากแก้ไขปัญหานี้แล้ว

  1. ใช้โครงร่างเฟรมที่คุณกำลังแทนที่ส่วนของคุณ

    <FrameLayout
                    android:id="@+id/fragment_place"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent" />
  2. และรหัสสำหรับการเปลี่ยน

    public void selectFrag(View view) {
    Fragment fr;
    
      if(view == findViewById(R.id.button2))
    {
         fr = new FragmentTwo();
    
     }else {
         fr = new FragmentOne();
     }
     FragmentManager fm = getFragmentManager();
     FragmentTransaction fragmentTransaction = fm.beginTransaction();
     fragmentTransaction.replace(R.id.fragment_place, fr);
     fragmentTransaction.commit();

ถ้าคุณต้องการตัวอย่างทั้งหมดฉันจะส่งความคิดเห็นให้คุณ ...


0

ฉันก็มีปัญหาเดียวกันเช่นกัน แต่เป็นเพราะฉันไม่ได้เปลี่ยนสีพื้นหลังของส่วนที่ฉันพยายามเพิ่มลงในเฟรมเลย์เอาต์

ลองทำสิ่งนี้ด้วยlayout_heightและlayout_widthตั้งค่าเป็นmatch_parent


0

ฉันเคยมีปัญหานี้ครั้งหนึ่งและพบว่าเป็นเพราะฉันได้ลบandroid:backgroundแอตทริบิวต์ที่ขาดหายไปในรหัส xml ของคุณโดยไม่ได้ตั้งใจ ฉันเชื่อว่ามันใช้งานได้เหมือนเวลาที่คุณวาดภาพผนังandroid:backgroundคือสีของผนังจะเป็นและมุมมองอื่น ๆ จะถูกวางไว้ด้านบนของสีฐานนั้น เมื่อคุณไม่ทาสีผนังก่อนกำหนดตำแหน่งมุมมองของคุณพวกเขาจะอยู่ด้านบนของสิ่งที่มีอยู่แล้วในกำแพงนั้นในกรณีของคุณส่วนอื่น ๆ ของคุณ ไม่รู้ว่าจะช่วยคุณได้หรือเปล่าขอให้โชคดี


0

ฉันได้ลองเหนือทุกกรณีและพยายามแก้ไขปัญหา แต่ยังไม่ได้รับการแก้ไข ฉันไม่รู้ว่าทำไมมันถึงไม่ได้ผลสำหรับฉัน ฉันเห็นด้วยกับคำตอบข้างต้นเพราะหลายคนเห็นด้วยกับมัน

ฉันแค่ขยายคำตอบและด้านล่างนี้คือวิธีที่ใช้ได้ผลสำหรับฉัน

ฉันได้เพิ่มคุณสมบัตินี้android:clickable="true"ในเค้าโครงหลักด้านบนของfragment.xmlไฟล์

ฉันหวังว่าใครบางคนจะได้รับความช่วยเหลือ


0

ขอขอบคุณ Sapan Diwakar และคนอื่น ๆ คำตอบนี้ช่วยฉัน ฉันเพิ่งสร้าง RelativeLayout โดยไม่มีส่วนภายในใช้ RelativeLayout เป็นมุมมองหลักหรือกลุ่มระบุมุมมองกลุ่มนั้นในธุรกรรมที่จะแทนที่และใช้งานได้

รหัส:

getSupportFragmentManager().beginTransaction()
                            .replace(R.id.content_group_view, itemDetailFragment).commit();

XML:

 <RelativeLayout
         android:id="@+id/content_group_view"
         android:layout_width="match_parent"
         android:layout_height="match_parent">

 </RelativeLayout>

0

ตรวจสอบรหัสโครงร่างเฟรมของคุณและแทนที่ตามด้านล่าง

fragmentTransactionChange = MainActivity.this.getSupportFragmentManager().beginTransaction();
fragmentTransactionChange.replace(R.id.progileframe, changeFragment);
fragmentTransactionChange.addToBackStack(null);
fragmentTransactionChange.commit();
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.