Android ViewPager获取当前视图


75

我有一个ViewPager,我想获取当前选定的可见视图,而不是位置。

  1. getChildAt(getCurrentItem) 返回错误 View
  2. 这并非始终有效。有时返回null,有时仅返回错误的View。

    @Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        super.setUserVisibleHint(isVisibleToUser);
    
        if (isVisibleToUser == true) { 
            mFocusedListView = ListView; 
        }
    }
    
  3. PageListener上ViewPagergetChildAt()也没有工作,每次都没有给我正确的观点。

如何获得当前的可见视图?

View view = MyActivity.mViewPager.getChildAt(MyActivity.mViewPager.getCurrentItem()).getRootView();
ListView listview = (ListView) view.findViewById(R.id.ListViewItems);

Answers:


133

我知道了。我所做的是setTag()使用所有Views / ListViews的名称进行调用findViewWithTag(mytag),然后仅调用,mytag即标签。

不幸的是,没有其他方法可以解决这个问题。


1
这给了我一个提示。谢谢!
rahstame,2013年

7
我不敢相信这是最好的选择,但它确实有效。我只是在适配器创建项目时将索引设置为标签。
尊重TheCode 2013年

13
+1荒谬的解决方案,但这绝对是最好的。使用位置作为PagerAdapter.instantiateView中的标记,并使用findViewBy(getCurrentItem())检索View是此技巧的最优雅形式。
nathanielwolf 2014年

寻找此解决方案的另一个+1 @lacas
Addi

4
请告诉我,将近六年后,有更好的方法可以做到这一点!
图论

9

我刚遇到相同的问题,并使用以下方法解决了问题:

View view = MyActivity.mViewPager.getFocusedChild();

5
即使您当前正在显示ViewPager的视图,有时也无法将焦点移到其他位置
Pimp Trizkit 2013年

可能是这样,但是如果您要求将注意力集中在可见的页面上,则可以使用
ZeCodea 2013年

1
除非,我在这里误解了一些东西。“请求焦点”具体是什么意思?因为如果我mViewPager.getChildAt(i).isFocused()为所有孩子做,它将false为所有孩子报告。这可能是因为我将这段代码放入MainActivity的options菜单中,从而将焦点从ViewPager移开了。因此,这种方式在某些情况下是行不通的。
Pimp Trizkit 2013年

是的,这可能是对话框弹出窗口或Toast对象。因此,请使用方法isVisible()代替
CodeToLife

似乎不适用于AndroidX ViewPager 1.0.0 /支持库ViewPager 28.0.0
Tim Kist,

7

您可以通过从适配器调用访问myAdapter.yourListItens.get(myViewPager.getCurrentItem()); itens列表来获取当前元素。如您所见,ViewPager可以检索适配器元素的当前索引(当前页面)。

如果您正在使用FragmentPagerAdapter,则可以执行以下强制转换:

FragmentPagerAdapter adapter = (FragmentPagerAdapter)myViewPager.getAdapter();

并打电话

adapter.getItem(myViewPager.getCurrentItem());

这对我来说很好;)


2
仅在适配器为FragmentPagerAdapter的情况下有效
Boris Strandjev 2014年

22
注意,getItem()应该在子类化时始终返回Fragment的新实例Fragment(State)PagerAdapter。因此,这是不对的,因为它只是创建一个新实例而不是返回“旧”实例。
ComFreek

上面的评论是错误的。直接从文档:“返回与指定位置关联的片段”。关于返回新的片段什么也没说。
工作

2
您的答案返回了片段,但对我来说,片段为空。adapter.getItem(myViewPager.getCurrentItem())。getView()返回null。
工作

7

我用这种方法 android.support.v4.view.ViewPager

View getCurrentView(ViewPager viewPager) {
        try {
            final int currentItem = viewPager.getCurrentItem();
            for (int i = 0; i < viewPager.getChildCount(); i++) {
                final View child = viewPager.getChildAt(i);
                final ViewPager.LayoutParams layoutParams = (ViewPager.LayoutParams) child.getLayoutParams();

                Field f = layoutParams.getClass().getDeclaredField("position"); //NoSuchFieldException
                f.setAccessible(true);
                int position = (Integer) f.get(layoutParams); //IllegalAccessException

                if (!layoutParams.isDecor && currentItem == position) {
                    return child;
                }
            }
        } catch (NoSuchFieldException e) {
            Log.e(TAG, e.toString());
        } catch (IllegalArgumentException e) {
            Log.e(TAG, e.toString());
        } catch (IllegalAccessException e) {
            Log.e(TAG, e.toString());
        }
        return null;
    }

非常感谢。这正是我想要的
Erfan Eghterafi

2

在寻找一种装饰android视图的方法的过程中,我认为我为博客中记录的OP问题定义了替代解决方案。我链接到它,因为代码似乎在这里包含所有内容都有点过多。

我提出的解决方案:

  • 使适配器和视图完全分开
  • 可以轻松地从视图分页器中查询具有任何索引的视图,null如果当前未加载该视图或相应的视图,则将返回该视图。

2

我使用ViewPagerUtilsFabulousFilter

ViewPagerUtils.getCurrentView(ViewPager viewPager)

我正在使用此方法,我可以确认它是否有效。
AleksandarAcić18年

这不是核心android SDK的一部分。您可能正在使用第三方库。这可能就是为什么你被否决了。
aeskreis

1
您在使用这个库吗?github.com/Krupen/FabulousFilter。该库具有ViewPagerUtils方法。它使用高度怀疑的android.support.v4命名空间。您永远不要为类使用android名称空间,因为它可能导致混淆(这是此类混淆的完美示例)。看来作者这样做是为了访问受程序包保护的字段,这再次是可怕的代码实践。我不推荐这种方法。
aeskreis

我在回答中写道,它是android支持库v4。developer.android.com/topic/libraries/support-library
AleksandarAcić18年

而且ViewPager是支持库的一部分,因此无需添加其他依赖项。
AleksandarAcić18年

2

使用扩展PagerAdapter的适配器,并在PagerAdapter内部重写setPrimaryItem方法。

https://developer.android.com/reference/android/support/v4/view/PagerAdapter.html

class yourPagerAdapter extends PagerAdapter
{
    // .......

    @Override
    public void setPrimaryItem (ViewGroup container, int position, Object object)
    {
        int currentItemOnScreenPosition = position;
        View onScreenView = getChildAt(position);
    }

    // .......

}

2
不回答原始问题以获取实际视图。另外,如果您想要该职位,为什么不使用getCurrentItem()呢?
蒂姆·基斯特

是。我忘了写那个来获取只需要使用的视图:getChildAt(currentItemOnScreenPosition)。
安德烈斯(Andrés)

另一方面,getCurrentItem()函数不会返回当前选定的可见视图,正如原始问题所述,getChildAt(getCurrentItem)返回错误的View。我认为getCurrentItem()函数返回当前由viewPager计算的项目,这个项目可能不是当前屏幕上的同
安德烈斯

1

尝试这个

 final int position = mViewPager.getCurrentItem();
    Fragment fragment = getSupportFragmentManager().findFragmentByTag("android:switcher:" + R.id.rewards_viewpager + ":"
            + position);

1

我不得不更常规地执行此操作,因此我决定使用ViewPager.LayoutParams的私有“位置”

        final int childCount = viewPager.getChildCount();
        for (int i = 0; i < childCount; i++) {
            final View child = viewPager.getChildAt(i);
            final ViewPager.LayoutParams lp = (ViewPager.LayoutParams) child.getLayoutParams();
            int position = 0;
            try {
                Field f = lp.getClass().getDeclaredField("position");
                f.setAccessible(true);
                position = f.getInt(lp); //IllegalAccessException
            } catch (NoSuchFieldException | IllegalAccessException ex) {ex.printStackTrace();}
            if (position == viewPager.getCurrentItem()) {
                viewToDraw = child;
            }
        }

1

如果没有太多页面,并且可以安全地将setOffscreenPageLimit(N-1) N表示为页面总数而不浪费太多内存,则可以执行以下操作:

public Object instantiateItem(final ViewGroup container, final int position) {      
    CustomHomeView RL = new CustomHomeView(context);
    if (position==0){
        container.setId(R.id.home_container);} ...rest of code

然后这是访问您的页面的代码

((ViewGroup)pager.findViewById(R.id.home_container)).getChildAt(pager.getCurrentItem()).setBackgroundColor(Color.BLUE);

如果需要,可以设置访问页面的方法

RelativeLayout getPageAt(int index){
    RelativeLayout rl =  ((RelativeLayout)((ViewGroup)pager.findViewById(R.id.home_container)).getChildAt(index));
    return rl;
}

2
getChildAt(pager.getCurrentItem())不会做你想要的。例如,ViewPager可以有1000页,但只能有5个孩子,因此如果当前项是最后一页,您将超出范围。
fdermishin

@fdermishin这是真的,除非您具有选项“ setOffscreenPageLimit(N-1)”,其中N是页面数。但是,如果您有很多页面,则不建议这样做,因为这可能会不必要地浪费内存
Michael Kern,

0

是您在屏幕上的第一个活动,还是已经在彼此之上进行了分层?

尝试这个:

findViewById(android.R.id.content).getRootView()

要不就:

findViewById(android.R.id.content) 

还取决于您想要尝试:

((ViewGroup)findViewById(android.R.id.content)).getChildAt(0)

前两个一直给我TAB 0项,第三个代码给我一个空
lacas 2012年

试过这个吗?this.findViewById(android.R.id.content).getRootView()也许您应该提供有关您的活动以及如何在活动之间进行构造和移动的更多信息。
SunnySonic 2012年

这些建议均无效。第三个将在寻呼机中获得一个页面,但不会获得中心视图,但会在左侧获得一个页面,OP希望获得居中/当前页面。
蒂姆·基斯

0

您可以按系统标签找到片段。对我来说有用。我在OnMeasure功能上使用它。

id -viewPager ID

position -您想要获得的片段

重要!如果您的片段是在适配器中创建的,则会得到此片段。所以你必须检查supportedFragmentManager.findFragmentByTag("android:switcher:" + id + ":" + position)无效

您可以这样获得视图:

supportedFragmentManager.findFragmentByTag("android:switcher:" + id + ":" + position).view

您不应该在适配器中提供自定义标签


0
viewpager.getChildAt(0)

这总是返回我当前选择的视图。这对我有用,但我不知道如何做。


-3

如果仔细检查,ViewPager最多保存3个视图。您可以通过以下方式轻松获取当前视图

view     = MyActivity.mViewPager.getChildAt(1);

1
这行不通。如果viewpager显示其首页或末页怎么办?如果屏幕外页面超过1个怎么办?
foo64 2013年

1
错误,您可以将ViewPager设置为使用setOffscreenPageLimit(int)
zyamys

-3

请检查一下

((ViewGroup))mViewPager.getChildAt(MyActivity.mViewPager.getCurrentItem()));

否则请验证此链接


无法正常工作,这不是可悲地看到的视图,有时甚至为空
lacas 2012年

3
这行不通。的范围getChildAt()不同于的范围getCurrentItem()。例如,如果您的ViewPager显示20个项目和1个离屏页面,则getChildAt()的范围是0-2,而getCurrentItem()的范围是0-19。您通常会得到空返回值。
foo64
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.