如何知道碎片是否可见?

时间:2013-05-20 14:46:54

标签: android android-fragments

我正在使用支持库v4,我的问题是,如何知道片段是否可见?如何更改碎片中膨胀的布局的属性?提前谢谢。

--- ---编辑

我正在使用像FragmentActivity的Android开发人员教程中的片段

12 个答案:

答案 0 :(得分:72)

您应该能够执行以下操作:

MyFragmentClass test = (MyFragmentClass) getSupportFragmentManager().findFragmentByTag("testID");
if (test != null && test.isVisible()) {
     //DO STUFF
}
else {
    //Whatever
}

答案 1 :(得分:20)

创建isVisible()后,isAdded()true都会返回Fragment,甚至实际上都不可见。真正有效的唯一解决方案是:

if (isAdded() && isVisible() && getUserVisibleHint()) {
    // ... do your thing
}

这可以胜任。周期。

答案 2 :(得分:16)

如果您想知道何时使用正在查看片段,您应该使用

yourFragment.isResumed()

而不是

yourFragment.isVisible()

首先isVisible()已检查isAdded(),因此无需同时调用这两者。其次,非这两个意味着用户实际上看到了你的片段。只有isResumed()才能确保您的片段位于用户面前,如果您正在寻找,那么用户可以与其进行互动。

答案 3 :(得分:14)

你可以这样试试:

Fragment currentFragment = getFragmentManager().findFragmentById(R.id.fragment_container);

Fragment currentFragment = getSupportFragmentManager().findFragmentById(R.id.fragment_container);

在此if中,检查currentFragment是否是YourFragment的实例

if (currentFragment instanceof YourFragment) {
     Log.v(TAG, "your Fragment is Visible");
}

答案 4 :(得分:9)

仅当片段位于视图上且可见

时,

getUserVisibleHint()才会出现

答案 5 :(得分:7)

您可以像这样覆盖setMenuVisibility:

@Override
public void setMenuVisibility(final boolean visible) {
   if (visible) {
      //Do your stuff here
   }

   super.setMenuVisibility(visible);
}

答案 6 :(得分:7)

需要注意的一点是,isVisible()会返回当前片段的可见状态。支持库中存在一个问题,如果您有嵌套的片段,并且隐藏了父片段(因此也隐藏了所有子片段),则孩子仍然会说它是可见的。

isVisible()是最终版,所以无法覆盖。我的解决方法是创建一个BaseFragment类,我的所有片段都扩展,然后创建一个类似的方法:

public boolean getIsVisible()
{
    if (getParentFragment() != null && getParentFragment() instanceof BaseFragment)
    {
        return isVisible() && ((BaseFragment) getParentFragment()).getIsVisible();
    }
    else
    {
        return isVisible();
    }
}

我做isVisible() && ((BaseFragment) getParentFragment()).getIsVisible();因为如果隐藏了任何的父片段,我们想要返回false。

这似乎对我有用。

答案 7 :(得分:1)

ArticleFragment articleFrag = (ArticleFragment)
            getSupportFragmentManager().findFragmentById(R.id.article_fragment);

    if (articleFrag != null && articleFrag.isVisible()) {

        // Call a method in the ArticleFragment to update its content
        articleFrag.updateArticleView(position);
    }

请参阅http://developer.android.com/training/basics/fragments/communicating.html

答案 8 :(得分:0)

以上解决方案均不适合我。 但是,以下内容就像一种魅力:-

<code>override fun setUserVisibleHint(isVisibleToUser: Boolean)</code>

答案 9 :(得分:0)

如果只有一个Fragment

,请尝试此操作
if (getSupportFragmentManager().getBackStackEntryCount() == 0) {
                    //TODO: Your Code Here
                }

答案 10 :(得分:0)

在这里添加一些我遇到的信息:

fragment.isVisible仅在true/false时有效(replaceFragment()),否则,如果您使用addFragment(),则isVisible始终返回true片段在其他片段的后面。

答案 11 :(得分:0)

以防万一您将 Fragment 布局与 ViewPager (TabLayout) 一起使用,您可以通过 ViewPager.getCurrentItem() 方法轻松请求当前(前面)的 Fragment。它会给你页面索引。

从页面索引映射到 fragment[class] 应该很容易,因为您已经在 FragmentPagerAdapter 派生适配器中进行了映射。

int i = pager.getCurrentItem();

您可以通过以下方式注册页面更改通知

ViewPager pager = (ViewPager) findViewById(R.id.container);
pager.addOnPageChangeListener(this);

当然你必须实现接口ViewPager.OnPageChangeListener

public class MainActivity 
    extends AppCompatActivity
    implements ViewPager.OnPageChangeListener
{
    public void onPageSelected (int position)
    {
        // we get notified here when user scrolls/switches Fragment in ViewPager -- so
        // we know which one is in front.
        Toast toast = Toast.makeText(this, "current page " + String.valueOf(position), Toast.LENGTH_LONG);
        toast.show();
    }

    public void onPageScrolled (int position, float positionOffset, int positionOffsetPixels) {
    }

    public void onPageScrollStateChanged (int state) {
    }
}

我在这里的回答可能有点离题。但作为 Android 应用程序的新手,我正面临着这个问题,并没有在任何地方找到答案。所以制定了上述解决方案并将其发布在这里 - 也许有人觉得它很有用。

编辑:您可以将此方法与片段订阅的 LiveData 结合使用。此外,如果你给你的 Fragments 一个页面索引作为构造函数参数,你可以在你的 Fragment 类中创建一个简单的 amIvisible() 函数。

在主活动中:

private final MutableLiveData<Integer> current_page_ld = new MutableLiveData<>();
public LiveData<Integer> getCurrentPageIdx() { return current_page_ld; }

public void onPageSelected(int position) {
    current_page_ld.setValue(position);
}

public class MyPagerAdapter extends FragmentPagerAdapter
{
    public Fragment getItem(int position) {
        // getItem is called to instantiate the fragment for the given page: But only on first
        // creation -- not on restore state !!!
        // see: https://stackoverflow.com/a/35677363/3290848
        switch (position) {
            case 0:
                return MyFragment.newInstance(0);
            case 1:
                return OtherFragment.newInstance(1);
            case 2:
                return XYFragment.newInstance(2);
        }
        return null;
    }
}

在片段中:

    public static MyFragment newInstance(int index) {
        MyFragment fragment = new MyFragment();
        Bundle args = new Bundle();
        args.putInt("idx", index);
        fragment.setArguments(args);
        return fragment;
    }

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (getArguments() != null) {
            mPageIndex = getArguments().getInt(ARG_PARAM1);
        }
        ...
    }
    
    public void onAttach(Context context)
    {
        super.onAttach(context);
        MyActivity mActivity = (MyActivity)context;

        mActivity.getCurrentPageIdx().observe(this, new Observer<Integer>() {
            @Override
            public void onChanged(Integer data) {
                if (data == mPageIndex) {
                    // have focus
                } else {
                    // not in front
                }
            }
        });
    }