首页 文章

如何获取当前显示的片段?

提问于
浏览
376

我在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实例?

30 回答

  • 0

    在事务中添加片段时,应使用标记 .

    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

  • 5

    我知道这是一个老帖子,但之前也遇到了麻烦 . 找到了一个在 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();
    
        }
    

    这对我有用,因为我不想遍历每个片段,我必须找到一个可见的片段 . 希望它也可以帮助其他人 .

  • 7

    这是我的解决方案,我发现它适用于低碎片方案

    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;
    }
    
  • 3

    每次显示片段时,都必须将其标记为backstack:

    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);
    }
    
  • 0

    我用来查找当前显示片段的是以下代码 . 它很简单,现在对我有用 . 它运行在包含片段的活动中

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

    reactive方式:

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

    我的方法基于try / catch,如下所示:

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

    但可能有更好的方法......

  • 1

    好吧,这个问题得到了很多观点和关注,但仍然没有包含我最终的最简单的解决方案 - 使用getFragments() .

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

    这有点晚了,但对于任何感兴趣的人:如果您知道FragmentManager中所需片段的索引,只需获取对它的引用并检查isMenuVisible()函数!这里 :

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

    如果 true 对用户可见,依此类推!

  • 2

    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
    }
    
  • 134

    受到泰尼回答的启发,这是我的两分钱 . 从大多数其他实现中修改很少 .

    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",如果它是您当前的活动或使用对您的活动的引用 .

  • 8

    SupportFragmentManager 中有一个名为 findFragmentById() 的方法 . 我在活动容器中使用它,如:

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

    这就是如何获得当前的 Fragment . 如果您有自定义 Fragment 并且需要检查它是什么 Fragment ,我通常使用 instanceof

    if (currentFragment() instanceof MyFrag){
        // Do something here
    }
    
  • 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);
        }
      }
    });
    
  • 3

    Sev's answer适用于您点击后退按钮或以其他方式更改后台堆叠时 .

    不过,我做了一些略微不同的事情 . 我在基础片段及其派生片段上有一个backstack更改侦听器设置,并且此代码位于侦听器中:

    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
    }
    
  • 0

    您可以查询将哪个片段加载到您的Activities内容框架中,并检索片段类或片段“简单名称”(作为字符串) .

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

    用法:

    Log.d(TAG, getCurrentFragment());
    

    输出:

    D/MainActivity: FragOne
    
  • 14

    这对我有用 . 我希望这可以帮助某人 .

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

    如果您从父活动中获取当前的Fragment实例,则可以

    findFragmentByID(R.id.container);
    

    这实际上是获取在视图上填充的片段的当前实例 . 我遇到过同样的问题 . 我不得不加载相同的片段两次,一个在backstack上 .

    以下方法不起作用 . 它只是得到一个带有标签的Fragment . 不要在这种方法上浪费你的时间 . 我确信它有它的用途但是获得同一片段的最新版本不是其中之一 .

    findFragmentByTag()
    
  • 4

    如果到这里你正在使用 Kotlin:

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

    R.id.fragment_containerid fragmentactivity 上展示

    或者如果你想要一个更好的解决方案:

    supportFragmentManager.findFragmentById(R.id.content_main)?.let {
        // the fragment exists
    
        if (it is FooFragment) {
            // The presented fragment is FooFragment type
        }
    }
    
  • 3
    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");
    }
    
  • 5

    检查此解决方案 . 它对我有用,可以获得当前的片段 .

    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");
            }
    
  • 1

    在主活动中,当新片段附加到活动时,将调用onAttachFragment(片段片段)方法 . 在此方法中,您可以获取当前片段的实例 . 但是,当从backstack弹出一个片段时,即当按下后退按钮将顶部片段放在堆栈顶部时,不会调用onAttachFragment方法 . 我仍然在寻找一个回调方法,当一个片段在活动中变得可见时,该方法在主活动中被触发 .

  • 0

    我遇到了类似的问题,我想知道按下后退键时最后显示的片段 . 我使用了一个非常简单的解决方案,对我有用 . 每时间我打开一个片段,在onCreate()方法中,我在我的单例中设置一个变量(用你的片段名称替换“myFragment”)

    MySingleton.currentFragment = myFragment.class;
    

    变量在单例中声明为

    public static Class currentFragment = null;
    

    然后在onBackPressed()我检查

    if (MySingleton.currentFragment == myFragment.class){
            // do something
            return;
        }
        super.onBackPressed();
    

    确保调用super.onBackPressed();在“返回”之后,否则应用程序将处理后退密钥,在我的情况下导致应用程序终止 .

  • 11

    在滚动片段的情况下,当您使用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)
    //         ...
              }
    
  • 7

    科特林方式;

    val currentFragment = supportFragmentManager.fragments.last()
    
  • 2

    也许最简单的方法是:

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

    它对我有用

  • 74

    在这些情况下,使用事件总线(如OttoEventBusRxJava Bus)尤其方便 .

    虽然这种方法不一定会将当前可见的片段作为对象(虽然也可以完成,但它会导致更长的调用链),但它允许您对当前可见的片段执行操作(通常是您想知道当前可见的片段) .

    • 确保您尊重片段生命周期并在适当的时间注册/取消注册事件总线

    • ,您需要知道当前可见的片段并执行一组操作 . 用活动 Bus 拍摄活动 .

    所有已注册到总线的可见片段都将执行必要的操作 .

  • 355

    有点奇怪,但我查看了FragmentManager $ FragmentManagerImpl,以下内容适用于我:

    public static Fragment getActiveFragment(Activity activity, int index)
    {
        Bundle bundle = new Bundle();
        String key = "i";
        bundle.putInt(key,index);
        Fragment fragment=null;
        try
        {
            fragment = activity.getFragmentManager().getFragment(bundle, key);
        } catch(Exception e){}
        return fragment;
    }
    

    获取第一个活动片段使用0作为索引

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

    这适合我 . 在遍历片段列表之前,需要执行空检查 . 可能存在堆栈上没有加载片段的情况 .

    可以将返回的片段与要放入堆栈的片段进行比较 .

  • 4

    请尝试这种方法.....

    private Fragment getCurrentFragment(){
        FragmentManager fragmentManager = getSupportFragmentManager();
        String fragmentTag = fragmentManager.getBackStackEntryAt(fragmentManager.getBackStackEntryCount() - 1).getName();
        Fragment currentFragment = getSupportFragmentManager()
    .findFragmentByTag(fragmentTag);
        return currentFragment;
    }
    
  • 1

    您可以使用以下代码获取当前片段

    FragmentClass f = (FragmentClass)viewPager.getAdapter().instantiateItem(viewPager, viewPager.getCurrentItem());
    

相关问题