ViewPager 中的 Recyclerviews

Posted

技术标签:

【中文标题】ViewPager 中的 Recyclerviews【英文标题】:Recyclerviews in ViewPager 【发布时间】:2015-07-22 04:40:37 【问题描述】:

我正在尝试让这个工作:我基本上希望在一个 ViewPager 中有两个 Recyclerviews。我遵循了本教程:http://android-java-development.blogspot.de/2012/05/system.html,但它似乎不起作用。我看起来视图寻呼机是空的,并且回收站视图没有显示出来。

这是我的布局代码:

<android.support.v4.widget.SwipeRefreshLayout
        android:id="@+id/pager_refresh_layout"
        android:layout_
        android:layout_
        android:paddingTop="@dimen/tab_height">

        <android.support.v4.view.ViewPager
            android:id="@+id/pager"
            android:layout_
            android:layout_
            android:background="@color/accent"/>
    </android.support.v4.widget.SwipeRefreshLayout>

还有我的 PageAdapter:

public class NewsPagerAdapter extends PagerAdapter 
    private Context context;
    private Vector<RecyclerView> recyclerViewList;
    private String[] titles;

    public NewsPagerAdapter(Context context, int titlesId) 
        this.context = context;
        this.recyclerViewList = new Vector<>();

        setTitles(titlesId);
    

    public void add(RecyclerView recyclerView) 
        recyclerViewList.add(recyclerView);
    

    public RecyclerView.Adapter getAdapterForViewAtIndex(int index) 
        return recyclerViewList.get(index).getAdapter();
    

    @Override
    public Object instantiateItem(ViewGroup container, int position) 
        container.addView(recyclerViewList.get(position),
                new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 100)
        );
        return container;
    

    @Override
    public int getCount() 
        return recyclerViewList.size();
    

    @Override
    public boolean isViewFromObject(View view, Object object) 
        return view.equals(object);
    

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) 
        container.removeView((View) object);
    

    @Override
    public CharSequence getPageTitle(int position) 
        return titles[position];
    

    public void setTitles(int titles) 
        this.titles = context.getResources().getStringArray(titles);
    

还有我的 onCreatView 方法:

GridLayoutManager layoutManager1 = new GridLayoutManager(getActivity(), getResources().getInteger(R.integer.news_column_count));

GridLayoutManager layoutManager2 = new GridLayoutManager(getActivity(), getResources().getInteger(R.integer.news_column_count));

RecyclerView listView1 = new RecyclerView(getActivity());
RecyclerView listView2 = new RecyclerView(getActivity());
listView1.setLayoutManager(layoutManager1);
listView2.setLayoutManager(layoutManager2);

NewsAdapter adapter1 = new NewsAdapter(getActivity(), null);
NewsAdapter adapter2 = new NewsAdapter(getActivity(), null);
adapter1.setOnItemClickListener(this);
adapter2.setOnItemClickListener(this);

listView1.setAdapter(adapter1);
listView2.setAdapter(adapter2);

newsPagerAdapter.add(listView1);
newsPagerAdapter.add(listView2);

newsViewPager.setAdapter(newsPagerAdapter);

这里我将光标对象传递给适配器:

@Override
    public void onLoadFinished(Loader<Cursor> loader, Cursor data) 
        ((NewsAdapter) newsPagerAdapter.getAdapterForViewAtIndex(0)).swapCursor(data);
    

【问题讨论】:

在我看来,您错过了以编程方式创建的 RecyclerViews 的布局参数。尝试对您的两个视图使用类似 RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT, 100); 的内容 非常感谢您的回复!不幸的是,回收站视图似乎仍然不可见 能否更新一下代码? 好的,看看适配器实现 我会做两件事,但让我先问你一个问题。你在哪里填充两个 RecyclerViews?如我所见,您将 null 作为 NewsAdapter 中的第二个参数传递(我假设它是集合)。我对吗?没有任何要渲染的项目,RecyclerView 将是空的(不可见) 【参考方案1】:

您必须扩展 FragmentPagerAdapterFragmentStatePagerAdapter 才能轻松嵌入 RecyclerView。如果您要在其生命周期内更新 ViewPager 内容,强烈建议使用 FragmentStatePagerAdapter

您必须创建额外的片段布局,包含RecyclerView

如果你想用SwipeRefreshLayout 更新你的ViewPager,不要用SwipeRefreshLayout 包裹它。相反,您必须在片段布局内有SwipeRefreshLayout

因此,对于您的片段,您可能会获得以下 xml:

<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.SwipeRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/listRefresh"
    android:layout_
    android:layout_>
    <android.support.v7.widget.RecyclerView
        android:id="@+id/categoryList"
        android:scrollbars="vertical"
        android:layout_
        android:layout_/>
</android.support.v4.widget.SwipeRefreshLayout>

并创建额外的 Fragment 类,它将膨胀该布局并实现方法,您将需要更新刷新指示器状态。

这里有一个老例子: http://developer.android.com/training/implementing-navigation/lateral.html

如果您希望将您的 ViewPager 与新的支持库 TabLayout 连接,它很容易与:

tabLayout.setupWithViewPager(viewPager);

最后,如果您要更新“碎片化”ViewPager,请不要尝试重置适配器,因为碎片不是使用适配器管理的,而是使用 FragmentManager 管理的。更新对应RecyclerViews的内容比较明智

public class MyFragmentedPagerAdapter extends FragmentStatePagerAdapter 
    private final TabLayout mTabLayout;
    private final SwipeRefreshLayout.OnRefreshListener mRefreshListener;
    private Vector<PriceListFragment> fragmentList;
    private Vector<String> titles;

    public MyFragmentedPagerAdapter(FragmentManager fm, MyComplexData data, OnCartActionListener listener, TabLayout tabLayout, SwipeRefreshLayout.OnRefreshListener refreshListener) 
        super(fm);
        mTabLayout = tabLayout;

        // external refresh listener, that will trigger an updateData() 
        mRefreshListener = refreshListener;

        fragmentList = new Vector<>();
        titles = new Vector<>();
        updateData(data);
    

    public void updateData(MyComplexData data) 
        boolean updateTabs = false;
        boolean hasNewData = false;

        Vector<String> newTitles = new Vector<>();

        int position = 0;
        for(TabContents tabContents : data.getTabContents()) 

            if(tabContents.getListContents() == null)
                continue;
            hasNewData = true;
            boolean isNewFragment;

            MyFragment fragment;
            try 
                fragment = fragmentList.get(position);
                isNewFragment = false;
             catch (ArrayIndexOutOfBoundsException e) 
                fragment = new MyFragment();
                isNewFragment = true;
            
            // Update the data, title and hide update indicator of SwipeRefreshLayout
            fragment.setTabContents(tabContents);

            newTitles.add(tabContents.getName());

            if(isNewFragment) 
                fragment.setRefreshListener(mRefreshListener);
                fragmentList.add(fragment);
            
            position++;
        

        if(!hasNewData)
            return;

        // we need to decide, whether to update tabs
        if(titles.size() != newTitles.size()) 
            updateTabs = true;
         else 
            for(position = 0; position < titles.size(); position++) 
                if(!titles.get(position).equals(newTitles.get(position))) 
                    updateTabs = true;
                    break;
                
            
        

        titles = newTitles;
        notifyDataSetChanged();

        if(updateTabs)
            mTabLayout.setTabsFromPagerAdapter(this);
    

    @Override
    public Fragment getItem(int position) 
        return fragmentList.get(position);
    

    // You need to override this method as well
    @Override
    public int getItemPosition(Object object) 
        MyFragment fragment = (MyFragment) object;
        String title = (String) fragment.getTitle();
        int position = titles.indexOf(title);

        if (position >= 0) 
            return position;
         else 
            return POSITION_NONE;
        
    

    @Override
    public int getCount() 
        return titles.size();
    

    @Override
    public CharSequence getPageTitle(int position) 
        return fragmentList.get(position).getTitle();
    

您的MyFragment 类必须实现getTitle() 方法。

【讨论】:

我会将此标记为答案,因为这与我得出的结论相同。我只是认为不使用片段会更有效,因为我为所有视图使用相同的基础数据集。无论如何,感谢您的帮助。 谢谢。我发布了这个答案,因为我无法为其他人找到任何关于这个问题的答案,包括我自己在内的其他人将来会搜索它=) 我已经扩展了 FragmentPagerAdapter 并且从几天开始试图找出 RecyclerView 不更新的原因。阅读您的回复后,我更改了扩展 FragmentStatePagerAdapter 并且它有效.. 谢谢您 不客气。令人难以置信的是,如此古老的答案仍然有用:)

以上是关于ViewPager 中的 Recyclerviews的主要内容,如果未能解决你的问题,请参考以下文章

如何用recyclerview和viewpager2实现exoplayer?

Realm和RecyclerView项目排序和自动ViewPager片段通信

ViewPager 滑动不适用于 RecyclerView

带有 Recyclerview 的 ViewPager 上的 NullPointerException

使用 recyclerview 和 Asynctask 设置 Viewpager

带有折叠工具栏的 RecyclerView 和 ViewPager