Android ViewPager 获取当前View

问题描述 投票:0回答:18

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

  1. getChildAt(getCurrentItem)
    返回错误
    View
  2. 这并不总是有效。有时返回 null,有时只是返回错误的 View。

    @Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        super.setUserVisibleHint(isVisibleToUser);
    
        if (isVisibleToUser == true) { 
            mFocusedListView = ListView; 
        }
    }
    
  3. PageListener on

    ViewPager
    getChildAt()
    也不起作用,每次都没有给我正确的视图。

如何获取当前可见视图?

View view = MyActivity.mViewPager.getChildAt(MyActivity.mViewPager.getCurrentItem()).getRootView();
ListView listview = (ListView) view.findViewById(R.id.ListViewItems);
android android-fragments tabs android-viewpager
18个回答
140
投票

我已经弄清楚了。我所做的就是调用

setTag()
,并为所有
View
/
ListView
命名,然后直接调用
findViewWithTag(mytag)
mytag
就是标签。

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


10
投票

我刚刚遇到了同样的问题并通过使用解决了它:

View view = MyActivity.mViewPager.getFocusedChild();

9
投票

我用这个方法

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

8
投票

您可以通过从适配器调用

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

如果您使用 FragmentPagerAdapter,您可以执行此转换:

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

并致电

adapter.getItem(myViewPager.getCurrentItem());

这对我来说非常有效;)


2
投票

在我努力寻找一种装饰 Android 视图的方法期间,我想我为 OP 的问题定义了替代解决方案,我已在我的博客中记录了该解决方案。我链接到它,因为代码似乎有点太多,无法包含这里的所有内容。

我提出的解决方案:

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

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
投票
viewpager.getChildAt(0)

这总是返回我当前选择的视图。这对我有用。


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
投票

我正在使用 FabulousFilter 中的 ViewPagerUtils

ViewPagerUtils.getCurrentView(ViewPager viewPager)

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

0
投票

这是您在屏幕上的第一个活动还是您已经将一些活动分层了?

试试这个:

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

或者只是:

findViewById(android.R.id.content) 

也取决于你想尝试什么:

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

0
投票

您可以通过系统标签查找片段。这对我来说是工作。我在

OnMeasure
函数中使用了它。

id
- viewPager ID

position
- 你想要获得的片段

重要!如果您的片段是在适配器中创建的,您将获得此片段。所以你必须检查

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

你可以得到这样的视图:

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

您不应该在适配器中给出自定义标签


0
投票

您可以通过viewpager监听器获取所选项目的位置

viewPager.addOnPageChangeListener(object : ViewPager.OnPageChangeListener{
        override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
            
        }

        override fun onPageSelected(position: Int) {
            
        }

        override fun onPageScrollStateChanged(state: Int) {
            
        }

    })

0
投票

使用这个方法。

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

如果有人知道这里的解决方案评论,它可能会在 androidx 中返回 null


0
投票

正确的方法是重写适配器类(RecyclerView.Adapter 的扩展)中的

onViewAttachedToWindow(holder: Holder)
方法。

此外,如果您想在刚刚滑开的视图上执行一些操作(释放资源、停止动画侦听器等),可以通过覆盖适配器类中的

onViewDetachedFromWindow(holder: Holder)
来完成。


-3
投票

如果仔细查看的话,ViewPager 最多保存了 3 个视图。 您可以通过

轻松获取当前视图
view     = MyActivity.mViewPager.getChildAt(1);

-3
投票

请检查这个

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

否则请验证此链接

© www.soinside.com 2019 - 2024. All rights reserved.