ฉันจะรับแฟรกเมนต์ที่แสดงอยู่ในปัจจุบันได้อย่างไร


445

ฉันกำลังเล่นกับชิ้นส่วนใน Android

ฉันรู้ว่าฉันสามารถเปลี่ยนส่วนได้โดยใช้รหัสต่อไปนี้:

FragmentManager fragMgr = getSupportFragmentManager();
FragmentTransaction fragTrans = fragMgr.beginTransaction();

MyFragment myFragment = new MyFragment(); //my custom fragment

fragTrans.replace(android.R.id.content, myFragment);
fragTrans.addToBackStack(null);
fragTrans.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
fragTrans.commit();

คำถามของฉันคือในไฟล์ Java ฉันจะรับอินสแตนซ์ Fragment ที่แสดงอยู่ในปัจจุบันได้อย่างไร


ที่เกี่ยวข้อง - stackoverflow.com/a/21104084/80428
Jay Wick

1
มีความเป็นไปได้ที่ซ้ำกันของการรับชิ้นส่วนวัตถุปัจจุบัน
ไม้ A.Suk

คำตอบ:


454

เมื่อคุณเพิ่มส่วนในธุรกรรมของคุณคุณควรใช้แท็ก

fragTrans.replace(android.R.id.content, myFragment, "MY_FRAGMENT");

... และใหม่กว่าถ้าคุณต้องการตรวจสอบว่าส่วนที่มองเห็นได้:

MyFragment myFragment = (MyFragment)getFragmentManager().findFragmentByTag("MY_FRAGMENT");
if (myFragment != null && myFragment.isVisible()) {
   // add your code here
}

ดูเพิ่มเติมที่http://developer.android.com/reference/android/app/Fragment.html


74
ตกลง แต่ฉันต้องการวิธีในการรับอินสแตนซ์ Fragment ที่แสดงอยู่ในปัจจุบันทันทีไม่ได้ตรวจสอบแฟรกเมนต์ทั้งหมดซ้ำแล้วตัดสินใจว่าชิ้นส่วนใดที่จะแสดงบนหน้าจอ ฉันคิดว่าคำตอบของคุณต้องการรหัสของฉันเพื่อตรวจสอบชิ้นส่วนของฉันซ้ำแล้วซ้ำอีกและหาคำตอบที่มองเห็นได้ ...
Leem.fin

33
ใช่ แต่อาจมีมากกว่าหนึ่งชิ้นส่วนที่มองเห็นได้ในแต่ละครั้ง ดังนั้นจึงไม่มีอะไรเหมือน "ชิ้นส่วนที่ใช้งานเท่านั้น" ....
ramdroid

6
ตกลงแม้จะมีชิ้นส่วนหลายชิ้นปรากฏขึ้นฉันก็ยังต้องการวิธีที่จะนำมันมา ... และวิธีที่ดีกว่าตรวจสอบชิ้นส่วนของฉันซ้ำแล้วซ้ำอีก ฉันกังวลเกี่ยวกับ "รับพวกเขา" วิธีการเช่น getDisplayedFragment () แต่ไม่แน่ใจว่ามีวิธีการดังกล่าวใน Android
Leem.fin

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

12
ทำไมทุกคนถึงไม่ยอมตอบคำถามนี้? แน่นอนว่าเป็นรหัสที่ดี แต่ไม่ตอบคำถามเพื่อให้ได้ชิ้นส่วนที่เฉพาะเจาะจงโดยแท็ก .. แต่ Asker ต้องการชิ้นส่วนที่แสดงอยู่ในปัจจุบันซึ่งหมายความว่าเขาไม่ทราบว่าจะแสดงส่วนใด ใช่อาจมีหลายแฟรกเมนต์ แต่การอ่านคำถามมีเพียงหนึ่งแฟรกเมนต์เท่านั้นที่แสดงบน UI ... ขออภัยที่ต้อง downvote เนื่องจากไม่ตอบคำถามบริบท
angryITguy

410

ฉันรู้ว่ามันเป็นโพสต์เก่า แต่ก็มีปัญหากับมันก่อนหน้านี้เช่นกัน พบวิธีแก้ปัญหาที่ต้องทำในonBackStackChanged()ฟังก์ชั่นการฟัง

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

         Fragment f = getActivity().getFragmentManager().findFragmentById(R.id.fragment_container);
      if(f instanceof CustomFragmentClass) 
        // do something with f
        ((CustomFragmentClass) f).doSomething();

    }

สิ่งนี้ใช้ได้กับฉันเนื่องจากฉันไม่ต้องการวนซ้ำทุกส่วนฉันต้องค้นหาสิ่งที่มองเห็นได้ หวังว่ามันจะช่วยคนอื่นด้วย


13
สิ่งที่ฉันกำลังมองหาเมื่อจัดการกับ onBackPressed () หลังการหมุนหน้าจอด้วยการนำทางลิ้นชัก ขอบคุณที่กลับมาแชร์สิ่งนี้
ShortFuse

1
ไม่พบการจัดเรียงไฟล์โดยวนซ้ำผ่านส่วนย่อยทั้งหมดภายในหรือไม่ :)
Andrew Senner

46
ในกรณีที่.getFragmentManagerรายงานประเภทที่เข้ากันไม่ได้เหมือนในกรณีของฉันมันเป็นเพราะฉันใช้android.support.app.v4.Fragmentซึ่งในกรณีที่วิธีการใช้งานที่ถูกต้องคือgetSupportFragmentManager
Răzvan Barbu

3
หรือคุณสามารถใช้findFragmentByTag()แทนfindFragmentByIdถ้าคุณได้ให้แท็กเป็นชิ้นส่วนเมื่อเพิ่มลงในfragmentManager.beginTransaction() .add(containerID, frag, fragmentTag) .addToBackStack(fragmentTag) .commit();
DeltaCap019

@AndrewSenner เขาหมายถึงว่าเขาไม่ต้องการที่จะทำอย่างชัดเจน :)
Farid

161

นี่คือทางออกของฉันที่ฉันพบว่ามีประโยชน์สำหรับสถานการณ์ส่วนน้อย

public Fragment getVisibleFragment(){
    FragmentManager fragmentManager = MainActivity.this.getSupportFragmentManager();
    List<Fragment> fragments = fragmentManager.getFragments();
    if(fragments != null){
        for(Fragment fragment : fragments){
            if(fragment != null && fragment.isVisible())
                return fragment;
        }
    }
    return null;
}

13
fragmentอาจเป็นค่าว่างในบางสถานการณ์เช่นเมื่อคุณป๊อปอัพสแต็กกลับ if (fragment != null && fragment.isVisible())ดังนั้นการใช้งานที่ดีขึ้น
cprcrack

8
วิธีการไม่สมบูรณ์เพราะเป็นไปได้มีเพียงไม่กี่ชิ้นเท่านั้นที่มองเห็นได้
letroll

ถ้าไม่สามารถมองเห็นแฟรกเมนต์ได้ fragmentManager.getFragments () จะส่งคืนค่า NULL ซึ่งจะนำไปสู่ ​​NPE ว่า "พยายามเรียกใช้เมธอดอินเตอร์เฟส 'java.util.Iterator java.util.List.iterator ()' ในการอ้างอิงวัตถุ NULL" ดังนั้นการวนรอบสำหรับควรถูกล้อมรอบด้วยการตรวจสอบง่าย ๆ : if (
แฟรกเมนต์

เกิดอะไรขึ้นถ้ามีชิ้นส่วนมากกว่าหนึ่งชิ้นที่มองเห็นได้
Shivaraj Patil

5
ในทางเทคนิคควรทำเครื่องหมายเป็นคำตอบตามคำถาม Asker ต้องการชิ้นส่วนที่แสดงอยู่ในปัจจุบันโดยไม่ทราบว่าเป็นส่วนใด คำตอบอื่น ๆ ให้ได้รับชิ้นส่วนตามแท็ก
angryITguy

76

ทุกครั้งที่คุณแสดงแฟรกเมนต์คุณต้องใส่แท็กในแบ็คสแต็ค:

FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.setTransition(FragmentTransaction.TRANSIT_ENTER_MASK);       
ft.add(R.id.primaryLayout, fragment, tag);
ft.addToBackStack(tag);
ft.commit();        

และเมื่อคุณต้องการรับแฟรกเมนต์ปัจจุบันคุณอาจใช้วิธีนี้:

public BaseFragment getActiveFragment() {
    if (getSupportFragmentManager().getBackStackEntryCount() == 0) {
        return null;
    }
    String tag = getSupportFragmentManager().getBackStackEntryAt(getSupportFragmentManager().getBackStackEntryCount() - 1).getName();
    return (BaseFragment) getSupportFragmentManager().findFragmentByTag(tag);
}

4
ฉันค่อนข้างแน่ใจว่าเทคนิคนี้ใช้ไม่ได้กับ Fragments ที่ใช้กับ ViewPager เนื่องจากไม่ได้เพิ่มด้วยแท็ก เพียงแค่โยนออกไปที่นั่น
loeschg

3
ดูเหมือนว่าจะใช้งานได้เมื่อคุณโทรaddToBackStack(tag)เท่านั้น แต่จะเกิดอะไรขึ้นถ้าคุณไม่ต้องการเพิ่มส่วนย่อย ๆ ใน back stack?
cprcrack

1
ใช้งานได้ก็ต่อเมื่อแท็กของคุณเหมือนกับชื่อสแต็กหลังซึ่งดูเหมือนจะผิดปกติ

จะเกิดอะไรขึ้นถ้าคุณเพิ่ม 5 แฟรกเมนต์ในธุรกรรมเดียวกัน
Kevin Lam

มันอาจจะดีที่จะบอกว่าถ้าคุณเรียกใช้ addToBackStack (null) สำหรับ Fragment ที่คุณไม่ต้องการชื่อเมธอด getName () สามารถส่งคืน null และคุณได้รับ NPE @ dpk, docu พูดว่า: รับชื่อที่แจกให้กับ FragmentTransaction.addToBackStack (String) เมื่อสร้างรายการนี้ นอกจากนี้ให้เพิ่มการตรวจสอบ null หาก EntryCount เป็น 0 และคุณพยายามรับรายการยอดนิยม
JacksOnF1re

23

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

    FragmentManager fragManager = this.getSupportFragmentManager();
    int count = this.getSupportFragmentManager().getBackStackEntryCount();
    Fragment frag = fragManager.getFragments().get(count>0?count-1:count);

3
คุณควรตรวจสอบให้แน่ใจว่ามีการนับ> 0 เพื่อให้ได้รับ (จำนวน -1) ไม่ได้โยน
ดัชนีนอกขอบเขตข้อยกเว้น

@ ได้รับสิ่งนี้จะไม่ให้ชิ้นส่วนที่ถูกแทนที่ แต่ไม่ได้เพิ่มใน backstack. ขวา? ถ้าใช่ฉันจะเอามันมาใช้โดยใช้อาร์กิวเมนต์แท็ก?
cafebabe1991

การเรียกใช้ getFragments จะไม่ให้ชิ้นส่วนตามลำดับที่เพิ่มเข้ามาหลังจากที่คุณเรียก popBackStack (null, FragmentManager.POP_BACK_STACK_INCLUSIVE) ในนั้นและเพิ่มชิ้นส่วนเพิ่มเติม
LEHO

หากกิจกรรมมีมากกว่าหนึ่งชิ้นส่วนมองเห็นได้วิธีของคุณไม่ถูกต้อง ตัวอย่างเช่น: ViewPager with Fragments ตามที่ฉันรู้จัก getBackStackEntryCount () ส่งคืนจำนวนการทำธุรกรรมไม่ใช่จำนวนของ
แฟรกเมนต์

คุณควรตรวจสอบfragManager.getFragments().size()แทนที่จะgetBackStackEntryCount()เป็นเพราะพวกเขาไม่จำเป็นต้องเท่ากัน (ซึ่งเป็นกรณีของฉัน) มิฉะนั้นคุณสามารถชนกับ IndexOutOfBoundsException
RustamG

19

วิธี Kotlin;

val currentFragment = supportFragmentManager.fragments.last()

ใช้งานได้กับ API 26 ขึ้นไปเท่านั้น
ibit

1
@ibit คุณหมายถึงอะไรกับการทำงานกับ API 26 ขึ้นไปเท่านั้น? ฉันลองใช้ตัวจำลอง API 19 ทำงานได้ดี
HendraWD

@HendraWD คุณถูกต้อง! ฉันอ้างถึงฟังก์ชั่นในgetFragments()ฟังก์ชั่นกรอบซึ่งเป็น API 26 ขึ้นไป
ibit

2
ดูแล. หากก่อนที่คุณจะไม่มีแฟรกเมนต์สแต็กใด ๆ ก็อาจทำให้เกิดข้อยกเว้นที่ว่างเปล่า
Jetwiz

มันใช้ไม่ได้เหรอ java.lang.ClassCastException: androidx.navigation.fragment.NavHostFragment ไม่สามารถร่ายไปที่ Fragment ได้
coolcool1994

13

ปฏิกิริยาทาง:

Observable.from(getSupportFragmentManager().getFragments())
    .filter(fragment -> fragment.isVisible())
    .subscribe(fragment1 -> {
        // Do something with it
    }, throwable1 -> {
        // 
    });

7
ปฏิกิริยานั้นเป็นอย่างไร คุณใช้สิ่งที่สังเกตได้ แต่จะปล่อยเพียงครั้งเดียวเท่านั้น
ทิม

6
และมันก็เป็นเพียง overkill forloop ที่ปรับปรุงแล้วจะทำแบบเดียวกันอาจจะเร็วกว่า
Peterstev Uremgba

การใช้สตรีมรีแอกทีฟสำหรับสตรีม api นั้นไม่ใช่สมาร์ทจริง ๆ แล้วพวกเขาบอกว่ามันเป็น overkill ใช้ไอ Java8 API ถ้าคุณต้องการที่จะรักษารายการเป็นสตรีมและใช้ตัวกรอง API
AndroidLover

13

วิธีการของฉันขึ้นอยู่กับลอง / จับเช่นนี้

MyFragment viewer = null;
    if(getFragmentManager().findFragmentByTag(MY_TAG_FRAGMENT) instanceOf MyFragment){
    viewer = (MyFragment) getFragmentManager().findFragmentByTag(MY_TAG_FRAGMENT);
}

แต่อาจมีวิธีที่ดีกว่า ...


1
คำถามของฉันคือวิธีการแสดงส่วนในปัจจุบันซึ่งหมายความว่าอาจมีจำนวนมากชิ้นฉันเพียงต้องการที่จะได้รับตัวอย่างของการแสดงในปัจจุบันทำไมต้องใช้ (MyFragment) ?? ฉันหมายความว่ามันอาจจะเป็นส่วนแสดงผลบนหน้าจอ ... และฉันต้องการที่จะได้รับการแสดงในปัจจุบัน
Leem.fin

MY_TAG_FRAGMENT เป็นแท็กของส่วนที่ฉันสร้างขึ้นก่อนที่จะใช้แทนที่เช่นนี้: fragmentTransaction.replace (R.id.FL_MyFragment, MyFragment, MY_TAG_FRAGMENT);
Thordax

หากฉันมีหลายแฟรกเมนต์ฉันสามารถใช้หนึ่งแท็กสำหรับแฟรกเมนต์ทั้งหมดเมื่อโทร. แทนที่ (... ) หรือไม่
Leem.fin

ใช่ไม่มีปัญหาให้ใช้รหัสนี้: fragmentTransaction.replace (R.id.FL_MyFragment, MyFragment, MY_TAG_FRAGMENT); และมันอาจเป็นไปด้วยดี
Thordax

1
ฉันไม่ได้รับคะแนนของคุณจริงๆฉันหมายถึงฉันต้องการวิธีรับอินสแตนซ์ Fragment ที่แสดงอยู่ในปัจจุบันทันทีไม่ตรวจสอบแฟรกเมนต์ทั้งหมดซ้ำแล้วจึงตัดสินใจว่าจะแสดงส่วนใดบนหน้าจอ
Leem.fin

11

คำถามนี้มีมุมมองและความสนใจมากมาย แต่ก็ยังไม่ได้มีทางออกที่ง่ายที่สุดจากฉัน - ใช้ getFragments ()

            List fragments = getSupportFragmentManager().getFragments();
            mCurrentFragment = fragments.get(fragments.size() - 1);

1
โชคไม่ดีที่สิ่งนี้ไม่เป็นความจริงเสมอไปการgetSupportFragmentManager().getFragments() ให้รายการของคุณกลับมา แต่ก็สามารถเก็บค่า Null ไว้ได้หากชิ้นส่วนล่าสุดเพิ่งถูกดึงออกมาจากแบ็คสแต็ค สม: ถ้าคุณตรวจสอบกับวิธีการของคุณภายในonBackStackChanged()วิธีการและคุณเรียกpopBackStack()ที่ไหนสักแห่งแล้วจะเป็นmCurrentFragment null
Stumi

@Stumi ขอบคุณสำหรับข้อมูลนี้ ใช่เสียงเหมือนหนึ่งในปัญหาวงจรชีวิตแปลก ๆ มากมายใน Android
Nativ

9

คุณสามารถเคียวรีแฟรกเมนต์ที่โหลดลงในเฟรมเนื้อหากิจกรรมของคุณและดึงคลาสแฟรกเมนต์หรือแฟรกเมนต์ 'Simple name' (เป็นสตริง)

public String getCurrentFragment(){
     return activity.getSupportFragmentManager().findFragmentById(R.id.content_frame).getClass().getSimpleName();
}

การใช้งาน:

Log.d(TAG, getCurrentFragment());

ขาออก:

D/MainActivity: FragOne

8

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

getSupportFragmentManager().getFragments().get(0).isMenuVisible()

ถ้าtrueมันปรากฏแก่ผู้ใช้และอื่น ๆ !


1
น่าแปลกที่นี่เป็นทางออกเดียวที่ปรากฏในที่นี้ซึ่งเหมาะกับฉัน ในเวลาเดียวกันหลายชิ้นส่วนสามารถมี,isVisible() == true getView() != nullนอกจากนี้ในรหัสของฉันgetBackStackEntryCountเป็นศูนย์เสมอ แม้ว่าฉันจะไม่ได้ใช้เมนู แต่isMenuVisible()ก็มีเพียงดิสต์เดียวที่ดูเหมือนจะชี้ไปที่ส่วนที่ 'ใช้งานอยู่' ในปัจจุบัน ty
parvus

7

1)

ft.replace(R.id.content_frame, fragment, **tag**).commit();

2)

FragmentManager fragmentManager = getSupportFragmentManager();
Fragment currentFragment = fragmentManager.findFragmentById(R.id.content_frame);

3)

if (currentFragment.getTag().equals(**"Fragment_Main"**))
{
 //Do something
}
else
if (currentFragment.getTag().equals(**"Fragment_DM"**))
{
//Do something
}

6

ถ้ามาที่นี่และคุณกำลังใช้Kotlin:

var fragment = supportFragmentManager.findFragmentById(R.id.fragment_container)

R.id.fragment_containerเป็นidที่ที่fragmentมีการนำเสนอของพวกเขาactivity

หรือถ้าคุณต้องการโซลูชันที่ดีกว่า:

supportFragmentManager.findFragmentById(R.id.content_main)?.let {
    // the fragment exists

    if (it is FooFragment) {
        // The presented fragment is FooFragment type
    }
}

5

แรงบันดาลใจจากคำตอบของTainyนี่คือสองเซ็นต์ของฉัน แก้ไขเล็กน้อยจากการใช้งานอื่น ๆ ส่วนใหญ่

private Fragment getCurrentFragment() {
    FragmentManager fragmentManager = myActivity.getSupportFragmentManager();
    int stackCount = fragmentManager.getBackStackEntryCount();
    if( fragmentManager.getFragments() != null ) return fragmentManager.getFragments().get( stackCount > 0 ? stackCount-1 : stackCount );
    else return null;
}

แทนที่"myActivity"ด้วย "this" หากเป็นกิจกรรมปัจจุบันของคุณหรือใช้อ้างอิงถึงกิจกรรมของคุณ


5

มีวิธีการที่เรียกว่าเป็นในfindFragmentById() SupportFragmentManagerฉันใช้ในภาชนะกิจกรรมเช่น:

public Fragment currentFragment(){
    return getSupportFragmentManager().findFragmentById(R.id.activity_newsfeed_frame);
}

Fragmentนั่นเป็นวิธีที่จะได้รับในปัจจุบันของคุณ หากคุณมีการกำหนดเองFragmentและจำเป็นต้องตรวจสอบFragmentมันคืออะไรฉันปกติใช้instanceof:

if (currentFragment() instanceof MyFrag){
    // Do something here
}

5

หากคุณกำลังใช้AndroidX Navigation:

val currentFragment = findNavController(R.id.your_navhost).?currentDestination

สำหรับข้อมูลเพิ่มเติมเกี่ยวกับองค์ประกอบการนำทางนี้: https://developer.android.com/guide/navigation/navigation-getting-started


สิ่งนี้ไม่ได้รวบรวม
IgorGanapolsky

1
มันจะรวบรวมถ้าคุณมีการติดตั้งอย่างถูกต้องนำทาง AndroidX และอย่างใดเรียกว่า your_navhostnavHost
คอรีรอย

4

นี่เป็นวิธีง่ายๆในการรับแฟรกเมนต์ปัจจุบัน ..

getFragmentManager().addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() {
  @Override public void onBackStackChanged() {
    currentFragment = fragmentManager.findFragmentById(R.id.content);
    if (currentFragment !=  null && (currentFragment instanceof LoginScreenFragment)) {
      logout.setVisibility(View.GONE);
    } else {
      logout.setVisibility(View.VISIBLE);
    }
  }
});

4

คำตอบของ Sevทำงานได้เมื่อคุณกดปุ่มย้อนกลับหรือเปลี่ยน backstack

แม้ว่าฉันจะทำสิ่งที่แตกต่างออกไปเล็กน้อย ฉันมีการติดตั้ง backstack listener change listener บนแฟรกเมนต์พื้นฐานและแฟรกเมนต์ที่ได้รับและโค้ดนี้อยู่ใน listener:

Fragment f = getActivity().getSupportFragmentManager().findFragmentById(R.id.container);

if (f.getClass().equals(getClass())) {
    // On back button, or popBackStack(),
    // the fragment that's becoming visible executes here,
    // but not the one being popped, or others on the back stack

    // So, for my case, I can change action bar bg color per fragment
}

3

นี่เป็นงานสำหรับฉัน ฉันหวังว่านี่จะทำให้มีคน

FragmentManager fragmentManager = this.getSupportFragmentManager();  
        String tag = fragmentManager
                    .getBackStackEntryAt(
                    fragmentManager
                    .getBackStackEntryCount() - 1)
                    .getName();
              Log.d("This is your Top Fragment name: ", ""+tag);

3

หากคุณได้รับอินสแตนซ์ปัจจุบันของ Fragment จากกิจกรรมหลักคุณสามารถทำได้

findFragmentByID(R.id.container);

สิ่งนี้จะได้รับเป็นอินสแตนซ์ปัจจุบันของแฟรกเมนต์ที่มีคนดูอยู่ ฉันมีปัญหาเดียวกัน ฉันต้องโหลดชิ้นส่วนเดียวกันสองครั้งเก็บหนึ่งไว้ข้างหลัง

วิธีการต่อไปนี้ใช้ไม่ได้ เพิ่งได้รับ Fragment ที่มีแท็ก อย่าเสียเวลากับวิธีนี้ ฉันแน่ใจว่ามันใช้แล้ว แต่เพื่อให้ได้ Fragment รุ่นเดียวกันล่าสุดไม่ใช่หนึ่งในนั้น

findFragmentByTag()

3

ชำระเงินโซลูชันนี้ มันทำงานให้ฉันเพื่อให้ได้ชิ้นส่วนปัจจุบัน

if(getSupportFragmentManager().getBackStackEntryCount() > 0){
        android.support.v4.app.Fragment f = 
         getSupportFragmentManager().findFragmentById(R.id.fragment_container);
        if(f instanceof ProfileFragment){
            Log.d(TAG, "Profile Fragment");
        }else if(f instanceof SavedLocationsFragment){
            Log.d(TAG, "SavedLocations Fragment");
        }else if(f instanceof AddLocationFragment){
            Log.d(TAG, "Add Locations Fragment");
        }

2
final FragmentManager fm=this.getSupportFragmentManager();
final Fragment fragment=fm.findFragmentByTag("MY_FRAGMENT");

if(fragment != null && fragment.isVisible()){
      Log.i("TAG","my fragment is visible");
}
else{
      Log.i("TAG","my fragment is not visible");
}

ใช้งานได้กับ Jetpack หรือไม่
IgorGanapolsky

2
getSupportFragmentManager().findFragmentById(R.id.content_frame).getClass().getSimpleName();

ฉันเดาว่านี่เป็นคำตอบที่ตรงไปตรงมาที่สุดสำหรับคำถามนี้ ฉันหวังว่านี่จะช่วยได้.


2

นี่คือวิธีแก้ปัญหา Kotlin:

if ( this.getSupportFragmentManager().getBackStackEntryCount()>0 ) {
    var fgmt = this.getSupportFragmentManager().fragments[this.getSupportFragmentManager().getBackStackEntryCount()-1]
    if( fgmt is FgmtClassName ) {
        (fgmt as FgmtClassName).doSth()
    }
}

วิธีที่ง่ายกว่า:

with ( this.getSupportFragmentManager() ) {
    if ( getBackStackEntryCount()>0 ) {
        var fgmt = fragments[getBackStackEntryCount()-1]
        if ( fgmt is FgmtClassName ) {
            (fgmt as FgmtClassName).doSth()
        }
    }
}

2

วิธีง่ายๆในการทำเช่นนั้น:

Fragment fr=getSupportFragmentManager().findFragmentById(R.id.fragment_container);
String fragmentName = fr.getClass().getSimpleName();

1

ในกิจกรรมหลักเมธอด onAttachFragment (Fragment Fragment) จะถูกเรียกเมื่อแฟรกเมนต์ใหม่เชื่อมต่อกับกิจกรรม ในวิธีนี้คุณจะได้รับอินสแตนซ์ของชิ้นส่วนปัจจุบัน อย่างไรก็ตามเมธอด onAttachFragment จะไม่ถูกเรียกเมื่อมีการแตกแฟรกเมนต์ออกจากแบ็คสแต็คเช่นเมื่อกดปุ่มย้อนกลับเพื่อรับแฟรกเมนต์ด้านบนที่ด้านบนของสแต็ก ฉันยังคงมองหาวิธีการโทรกลับซึ่งจะถูกเรียกใช้ในกิจกรรมหลักเมื่อมีชิ้นส่วนปรากฏในกิจกรรม


ใกล้มาก! :-)
Blundell

เราใช้ไลบรารีการนำทาง Jetpack
IgorGanapolsky

1

ในกรณีของชิ้นส่วนที่เลื่อนเมื่ออินสแตนซ์การใช้งานของคลาส ViewPager สมมติว่า mVeiwPager คุณสามารถโทร mViewPager.getCurrentItem () เพื่อรับหมายเลข int แฟรกเมนต์ปัจจุบัน

ใน MainLayout.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    android:orientation="vertical"
    tools:context="unidesign.photo360.MainActivity">

    <android.support.design.widget.AppBarLayout
        android:id="@+id/appbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:fitsSystemWindows="false"
        android:theme="@style/AppTheme.AppBarOverlay"
        app:expanded="false">

        <android.support.v7.widget.Toolbar
            android:id="@+id/main_activity_toolbar"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            app:popupTheme="@style/AppTheme.PopupOverlay"
            app:title="@string/app_name">

        </android.support.v7.widget.Toolbar>

    </android.support.design.widget.AppBarLayout>


    <android.support.v4.view.ViewPager
        android:id="@+id/view_pager"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

    </android.support.v4.view.ViewPager>
    
</android.support.design.widget.CoordinatorLayout>

ใน MainActivity.kt

class MainActivity : AppCompatActivity() {
    
        lateinit var mViewPager: ViewPager
        lateinit var pageAdapter: PageAdapter
        
//      ...
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
            
            pageAdapter = PageAdapter(supportFragmentManager)
            mViewPager = findViewById(R.id.view_pager)
//          ...
            }
            
        override fun onResume() {
          super.onResume()
          var currentFragment = pageAdapter.getItem(mViewPager.currentItem)
//         ...
          }


1

ฉันพบว่าfindFragmentByTagไม่สะดวก ถ้าคุณมีString currentFragmentTagในของคุณActivityพ่อแม่หรือFragmentคุณจะต้องบันทึกไว้ในและเรียกคืนในonSaveInstanceState onCreateแม้ว่าคุณจะทำเช่นนั้นเมื่อการActivityสร้างใหม่onAttachFragmentจะถูกเรียกก่อนหน้าonCreateนี้ดังนั้นคุณจึงไม่สามารถใช้currentFragmentTagในonAttachFragment(เช่นอัปเดตบางมุมมองตามcurrentFragmentTag ) เนื่องจากอาจไม่ได้รับการเรียกคืน

ฉันใช้รหัสต่อไปนี้:

Fragment getCurrentFragment() {
    List<Fragment> fragments = getSupportFragmentManager().getFragments();
    if(fragments.isEmpty()) {
        return null;
    }
    return fragments.get(fragments.size()-1);
}

เอกสารของFragmentManagerรัฐว่า

ลำดับของแฟรกเมนต์ในรายการคือลำดับที่เพิ่มหรือแนบ

เมื่อคุณจำเป็นต้องทำสิ่งที่ขึ้นอยู่กับชนิดส่วนในปัจจุบันเพียงแค่ใช้แทนgetCurrentFragment() instance of MyFragmentcurrentFragmentTag.equals("my_fragment_tag")

โปรดทราบว่าgetCurrentFragment()ในonAttachFragmentจะไม่ได้รับการแนบFragmentแต่ก่อนหน้านี้ที่แนบมา


1

ฉันต้องทำสิ่งนี้เมื่อเร็ว ๆ นี้และไม่มีคำตอบที่เหมาะสมกับสถานการณ์นี้จริงๆ

หากคุณมั่นใจว่ามีเพียงส่วนเดียวเท่านั้นที่สามารถมองเห็นได้ (เต็มหน้าจอ) ดังนั้นต้องการค้นหาสิ่งที่อยู่ด้านบนสุดของแบ็คสแต็ค ตัวอย่างเช่นKotlinสำหรับFragment:

import androidx.fragment.app.Fragment

fun Fragment.setVisibilityChangeListener(clazz: Class<out Fragment>, listener: (Boolean) -> Unit) {
    fragmentManager?.run {
        addOnBackStackChangedListener {
            val topFragmentTag = getBackStackEntryAt(backStackEntryCount - 1).name
            val topFragment = findFragmentByTag(topFragmentTag)
            listener(topFragment != null && topFragment::class.java == clazz)
        }
    }
}

และใช้มันเช่น:

class MyFragment: Fragment {
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        setVisibilityChangeListener(this::class.java) { visible -> 
            // Do stuff
        }
    }
}

1

คุณสามารถทำได้อย่างง่ายดายด้วย URL ใน logcat ซึ่งจะนำคุณไปยังซอร์สโค้ดของซอร์สโค้ดแฟรกเมนต์ปัจจุบัน ก่อนอื่นคุณต้องเพิ่มOnBackStackChangedListenerในกิจกรรมโฮสต์เช่น -

activity.getChildFragmentManager().addOnBackStackChangedListener(backStackListener);

และการใช้งานOnBackStackChangedListenerคือ -

    public FragmentManager.OnBackStackChangedListener backStackListener = () -> {

    String simpleName = "";
    String stackName = getStackTopName().trim();

    if (Validator.isValid(stackName) && stackName.length() > 0) {

      simpleName = stackName.substring(Objects.requireNonNull(stackName).lastIndexOf('.') + 1).trim();

      List<Fragment >
       fragmentList = getChildFragmentManager().getFragments();
      Fragment myCurrentFragment;

      for (int i = 0; i < fragmentList.size(); i++) {
       myCurrentFragment= fragmentList.get(i);
       if (myCurrentFragment.getClass().getSimpleName().equals(simpleName)) {
        //Now you get the current displaying fragment assigned in myCurrentFragment.
        break;
       }
       myFragment = null;
      }
     }


     //The code below is for the source code redirectable logcat which would be optional for you.
     StackTraceElement stackTraceElement = new StackTraceElement(simpleName, "", simpleName + ".java", 50);
     String fileName = stackTraceElement.getFileName();
     if (fileName == null) fileName = "";
     final String info = "Current Fragment is:" + "(" + fileName + ":" +
     stackTraceElement.getLineNumber() + ")";
     Log.d("now", info + "\n\n");
    };

และวิธีการgetStackTopName () คือ -

public String getStackTopName() {
    FragmentManager.BackStackEntry backEntry = null;
    FragmentManager fragmentManager = getChildFragmentManager();
    if (fragmentManager != null) {
        if (getChildFragmentManager().getBackStackEntryCount() > 0)
            backEntry = getChildFragmentManager().getBackStackEntryAt(
                    getChildFragmentManager().getBackStackEntryCount() - 1
            );
    }
    return backEntry != null ? backEntry.getName() : null;
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.