โปรแกรมย้อนกลับไปที่แฟรกเมนต์ก่อนหน้านี้ในแบ็คสแต็ค


218

ว่าฉันมีกิจกรรมที่มีส่วนเพิ่มทางโปรแกรม:

private void animateToFragment(Fragment newFragment, String tag) {
    FragmentTransaction ft = getFragmentManager().beginTransaction();
    ft.replace(R.id.fragment_container, newFragment, tag);
    ft.addToBackStack(null);
    ft.commit();
}

วิธีที่ดีที่สุดในการกลับไปยังส่วนก่อนหน้านี้ที่มองเห็นคืออะไร?

ฉันพบฟังก์ชันการทำงานของปุ่มย้อนกลับบนปุ่มคลิกใน Androidแต่ฉันคิดว่าการจำลองเหตุการณ์ปุ่มย้อนกลับไม่ใช่วิธีที่เหมาะสมในการดำเนินการ (และฉันไม่สามารถทำให้มันทำงานได้):

dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_BACK));

การโทรfinish()เพิ่งปิดกิจกรรมที่ฉันไม่สนใจ

มีวิธีที่ดีกว่าที่จะไปเกี่ยวกับเรื่องนี้?

คำตอบ:


354

ดูgetFragmentManager().popBackStack()วิธีการ (มีหลายวิธีให้เลือก)

http://developer.android.com/reference/android/app/FragmentManager.html#popBackStack ()


91
getFragmentManager().popBackStackImmediate();ทำเคล็ดลับ ขอบคุณ
Aske B.

1
ฉันจะวางวิธีนี้ไว้ที่ไหน ในฟังแท็บของฉัน?
rasen58

1
มันยากที่จะพูดว่า ... แต่มันควรจะอยู่ในส่วนของรหัสที่ถูกเรียกใช้เมื่อคุณต้องการที่จะ "ปิด" ชิ้นส่วนปัจจุบันและกลับไปที่ส่วนก่อนหน้า
หยุด

1
getSupportFragmentManager ()
ViliusK

5
อย่าลืมเพิ่ม "addToBackStack (" แท็ก ")" ในรหัสของคุณ "fragmentManager.beginTransaction () แทน (R.id.content_frame ชิ้น) .addToBackStack (" แท็ก ") กระทำ ();". ถ้าคุณเขียน addToBackStack (null) มันจะจัดการมันเอง แต่ถ้าคุณให้แท็กคุณควรจัดการด้วยตนเอง
Khaled Saif

129

เพื่ออธิบายรายละเอียดของคำตอบอื่น ๆ นี่เป็นวิธีแก้ปัญหาของฉัน (วางในกิจกรรม):

@Override
public void onBackPressed(){
    FragmentManager fm = getFragmentManager();
    if (fm.getBackStackEntryCount() > 0) {
        Log.i("MainActivity", "popping backstack");
        fm.popBackStack();
    } else {
        Log.i("MainActivity", "nothing on backstack, calling super");
        super.onBackPressed();  
    }
}

5
และทำไมจึงเกิดขึ้น ในตัวอย่างชิ้นส่วนdeveloper.android.com/training/basics/fragments/index.htmlพวกเขาไม่ได้เอาชนะเหตุการณ์ onbackpressed และพวกเขายังสามารถ backstack fragment ได้ ฉันใช้ trasaction.addToBackStack (null); แต่ไม่มีอะไรเกิดขึ้น คุณอธิบายได้ไหม
Murtaza Khursheed Hussain

@MurtazaHussain คุณควรถามคำถามใหม่หากคุณต้องการความช่วยเหลือ เป็นการยากที่จะดูว่าเกิดอะไรขึ้นโดยไม่ดูรหัสเพิ่มเติม
Kyle Falconer

2
ในกรณีของฉันฉันต้องทำfm.getBackStackEntryCount() > 1เพื่อเรียกกิจกรรมกลับเมื่อมีเพียงส่วนแรกในกอง
Facundo Olano

3
Android ทำสิ่งนี้ให้คุณแล้ว: "เมื่อมีวัตถุ FragmentTransaction บนสแต็กหลังและผู้ใช้กดปุ่มย้อนกลับ FragmentManager จะแสดงธุรกรรมล่าสุดออกจากสแต็กหลังและดำเนินการย้อนกลับ (เช่นลบแฟรกเมนต์ถ้าธุรกรรม เพิ่มมัน) " (ที่มา)
artkoenig

29

เมื่อเรากำลังปรับปรุง / เพิ่มชิ้นส่วน

.addToBackStack()ควรจะรวมถึง

getSupportFragmentManager().beginTransaction()
    .add(detailFragment, "detail") // Add this transaction to the back stack (name is an optional name for this back stack state, or null).
    .addToBackStack(null)
    .commit();

หลังจากนั้นถ้าเราให้ความgetFragments.popBackStackImmediate()ประสงค์จะกลับเป็นจริงถ้าเราเพิ่ม / อัปเดตชิ้นส่วนและย้ายกลับไปที่หน้าจอปัจจุบัน


7

เพิ่มบรรทัดเหล่านั้นในวิธีการ onBackPressed () ของคุณ popBackStackImmediate () วิธีการจะนำคุณกลับไปที่ส่วนก่อนหน้าถ้าคุณมีส่วนใด ๆ ในกองหลัง '

if(getFragmentManager().getBackStackEntryCount() > 0){
     getFragmentManager().popBackStackImmediate();
}
else{
    super.onBackPressed();
}

`


5

โซลูชันนี้ทำงานได้อย่างสมบูรณ์แบบสำหรับการนำทางชิ้นส่วนตามแถบด้านล่างเมื่อคุณต้องการปิดแอปเมื่อกดกลับในส่วนหลัก

ในทางกลับกันเมื่อคุณกำลังเปิดแฟรกเมนต์สำรอง (แฟรกเมนต์ในแฟรกเมนต์) ซึ่งถูกกำหนดเป็น "DetailedPizza" ในโค้ดของฉันมันจะส่งคืนสถานะก่อนหน้าของแฟรกเมนต์หลัก ไชโย!

ภายในกิจกรรมที่กดด้านหลังใส่สิ่งนี้:

Fragment home = getSupportFragmentManager().findFragmentByTag("DetailedPizza");

if (home instanceof FragmentDetailedPizza && home.isVisible()) {
    if (getFragmentManager().getBackStackEntryCount() != 0) {
        getFragmentManager().popBackStack();
    } else {
        super.onBackPressed();
    }
} else {
    //Primary fragment
    moveTaskToBack(true);
}

และเปิดตัวชิ้นส่วนอื่น ๆ เช่นนี้:

Fragment someFragment = new FragmentDetailedPizza();
FragmentTransaction transaction = getFragmentManager().beginTransaction();
transaction.replace(R.id.container_body, someFragment, "DetailedPizza");
transaction.addToBackStack("DetailedPizza");
transaction.commit();

3

คำตอบเหล่านี้ใช้ไม่ได้หากฉันไม่ได้เพิ่ม addToBackStack () ลงในธุรกรรมส่วนของฉัน แต่คุณสามารถใช้:

getActivity().onBackPressed();

จากส่วนใด ๆ ของคุณเพื่อย้อนกลับไปหนึ่งขั้นตอน


1

โดยทางโปรแกรมกลับไปที่แฟรกเมนต์ก่อนหน้าโดยใช้รหัสต่อไปนี้

if ( getFragmentManager().getBackStackEntryCount() > 0) 
{
          getFragmentManager().popBackStack();
          return;
}
super.onBackPressed();

1

หากต้องการทำให้ชิ้นส่วนนั้นกลับมาอีกเพียงเพิ่มชิ้นส่วนนั้นลงในแบ็คสแต็คที่คุณต้องการกดทับเช่น:

button.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        Fragment fragment = new LoginFragment();
        //replacing the fragment
        if (fragment != null) {
            FragmentTransaction ft = ((FragmentActivity)getContext()).getSupportFragmentManager().beginTransaction();
            ft.replace(R.id.content_frame, fragment);
            ft.addToBackStack("SignupFragment");
            ft.commit();
        }
    }
});

ในกรณีดังกล่าวข้างต้นที่ผมกำลังเปิดLoginFragmentเมื่อถูกกดในขณะนี้ผู้ใช้ที่อยู่ในButton button SignupFragmentดังนั้นหากaddToBackStack(TAG)จะเรียกว่าที่TAG = "SignupFragment"แล้วเมื่อปุ่มย้อนกลับถูกกดในเรากลับมาLoginFragmentSignUpFragment

Happy Coding!


ฉันคิดว่าแท็กจะไม่ส่งผลกระทบแม้กระทั่งอาจเป็นโมฆะ
CoolMind

1

เมื่อเพิ่มfragment_tran.addToBackStack(null)ชิ้นส่วนสุดท้ายฉันสามารถกลับมาใช้ชิ้นส่วนสุดท้ายได้

เพิ่มส่วนใหม่ :

view.findViewById(R.id.changepass).setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            FragmentTransaction transaction = getActivity().getSupportFragmentManager().beginTransaction();
            transaction.replace(R.id.container, new ChangePassword());
            transaction.addToBackStack(null);
            transaction.commit();
        }
    });

1

ฉันมาที่นี่เพื่อค้นหาหรือความคิดเดียวกันและในขณะเดียวกันฉันก็มาด้วยตัวเองซึ่งฉันเชื่อว่ามันไม่เลวและทำงานได้กับ ViewPager

ดังนั้นสิ่งที่ฉันทำคือแทนที่เมธอด onBackPressed ในกิจกรรมพาเรนต์ที่เก็บ viewPager และตั้งค่าให้ย้อนกลับลบ 1 ตำแหน่งเสมอจนกว่าจะถึงแฟรกเมนต์แรกจากนั้นปิดกิจกรรม

@Override
public void onBackPressed() {
    if(viewPager.getCurrentItem()>0){
        viewPager.setCurrentItem(viewPager.getCurrentItem()-1);
    } else {
        super.onBackPressed();
        this.close();
    }
}

private void close(){
    this.finish();
}

นี่อาจมีความพินาศเหมือนกลับไปทางเดียวในแต่ละครั้งดังนั้นมันอาจไม่ได้ผลหากมีแท็บและคุณสลับตำแหน่งด้วยการข้ามส่วน (จาก 0 ถึง 2 แล้วกดกลับจะทำให้คุณ 1 แทน 0)

สำหรับกรณีของฉันที่มี 2 แฟรกเมนต์ใน viewPager โดยไม่มีแท็บมันทำงานได้ดี


คำถามที่คล้ายกันตอบแล้ว stackoverflow.com/questions/10863572/…
AtifSayings

0

ลองรหัสด้านล่าง:

@Override
    public void onBackPressed() {
        Fragment myFragment = getSupportFragmentManager().findFragmentById(R.id.container);
        if (myFragment != null && myFragment instanceof StepOneFragment) {
            finish();
        } else {
            if (getSupportFragmentManager().getBackStackEntryCount() > 0) {
                getSupportFragmentManager().popBackStack();
            } else {
                super.onBackPressed();
            }
        }
    }
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.