如何测试片段视图是否对用户可见?


73

我有一个ViewPager,每个页面都是一个Fragment视图。我想测试片段是否在可见区域中。Fragment.isVisible仅测试

  • 片段附加到活动上
  • 片段设置为可见
  • 该片段已添加到视图

ViewPager将创建3个(默认情况下)片段,并且所有三个片段均满足上述条件,但实际上只有一个对用户可见(人


请发布您的代码以获得更好的帮助。
拉吉2012年

4
我当然也很想知道这一点。
曼弗雷德·摩泽

Answers:


19

您是对的,有更好的方法可以做到这一点!

在线查看FragmentPagerAdapter Javadoc,您会看到有一个方法setPrimaryItem(ViewGroup container,int position,Object object):避免完全执行所需的操作。

从javadoc

public void setPrimaryItem(ViewGroup容器,int位置,Object对象)

被调用以通知适配器当前哪个项目被视为“主要”项目,即作为当前页面显示给用户的项目。

参数容器将从其中删除页面的包含View。position现在是主要页面位置。object InstantiateItem(View,int)返回的同一对象。

注意滚动状态

现在,如果实现了这一点并开始调试以了解何时确切调用此方法,您将很快注意到在准备片段和用户轻扫时已多次触发该操作。

因此,最好还附加一个ViewPager.OnPageChangeListener,并且仅在viewpagers滚动状态再次变为SCOLL_STATE_IDLE时才执行必须做的事情。


1
如果可以扩展Application该类并必须测试是否显示了特定的UI,则此方法效果很好。我刚结束时使用了几个布尔值来测试应用程序是否已后台运行,以及是否显示了特定片段。
某处某人2014年

67

这就是我用来确定片段可见性的方法。

private static boolean m_iAmVisible;

@Override
public void setUserVisibleHint(boolean isVisibleToUser) { 
    super.setUserVisibleHint(isVisibleToUser);
    m_iAmVisible = isVisibleToUser;

    if (m_iAmVisible) { 
        Log.d(localTAG, "this fragment is now visible");
    } else {  
        Log.d(localTAG, "this fragment is now invisible");
    }
}

按照文档的说明,此操作不起作用:“为系统设置有关该片段的UI当前是否对用户可见的提示。该提示默认为true,并且在片段实例状态保存和还原时保持不变”
爱迪生

1
好的解决方案(+1),但是代码可以简化: public void setUserVisibleHint(boolean isVisibleToUser) { super.setUserVisibleHint(isVisibleToUser); m_iAmVisible = false; //default to not visible if (isVisibleToUser) { m_iAmVisible = true; } }
PeteH 2013年

2
简化为:public void setUserVisibleHint(boolean isVisibleToUser){super.setUserVisibleHint(isVisibleToUser); m_iAmVisible = isVisibleToUser;}
Kasas 2013年

30
甚至更简单getUserVisibleHint()
Leonardo Pinto 2014年

1
这非常感谢您!
Lazar Kukolj '16

9

出于我的目的,当Fragment可见时,它可以ViewPager.OnPageChangeListener.onPageSelected()与配合使用Fragment.onActivityCreated()来执行一个动作。Fragment.getUserVisibleHint()也有帮助。


3

我正在使用“ setMenuVisibility”-方法来解决此问题。由于每个片段都可以具有操作栏项,因此您可以在其中确定用户当前可见的片段。

@Override
public void setMenuVisibility(final boolean visible) {
    super.setMenuVisibility(visible);
    if (!visible) {
        //not visible anymore
    }else{
        yay visible to the user
    }
}

3

什么是错的使用getView().isShown(),以找出是否一个片段其实是可见的?


你测试过你的想法了吗?我认为这篇文章指出了相同的想法。
David S.

是。如链接文章中所建议,它对我有用。
2015年

3
isVisible() 

即使该片段在活动之后,仍可以返回true。

我正在使用以下内容:

if (getView() != null && getView().isShown()) {
//your code here
}

1
根据isShown类似于getVisibility()因此它可以,如果仍然返回true VISIBLE,但活动的背后
Mysterious_android

2

如果知道每个片段都附在什么“页面”上,则可以使用ViewPager.getCurrentItem()确定哪个片段“可见”。


4
这就是我现在正在做的。我只是在想是否还有其他方法。谢谢
David S.

0

在我的情况下,当用户看到片段时,ia必须对第一个片段做一些工作

 @Override
public void onWindowFocusChanged(boolean hasFocus) {
    super.onWindowFocusChanged(hasFocus);


    if(viewPager.getAdapter() instanceof YourPager)
    {
        Fragment fragemnt=((YourPager)viewPager.getAdapter()).getFragment(0); //getFragment(int index) custom method
        if( fragemnt instanceof YourFragment)
        {
            ((YourFragment)fragemnt).methodWhochShouldBeCalledAfterUIVisible();
        }
    }
}

0

setUserVisibleHint可能不会被调用,onHiddenChanged可能在每次关闭另一个片段时都不被调用。因此,您可能依赖onResume(和onPause),但是通常调用它的频率太高(例如,打开设备屏幕时)。同样在某些情况下不调用它,您应该在主机活动中管理当前片段并编写:

if (currentFragment != null) {
    currentFragment.onResume();
}

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.