ViewPager 中的 Recyclerviews
Recyclerviews in ViewPager
我正在尝试让它工作:我基本上想要在一个 ViewPager 中包含两个 Recyclerview。我遵循了本教程:http://android-java-development.blogspot.de/2012/05/system.html,但它似乎不起作用。我看起来 view pager 是空的,recycler view 没有显示。
这是我的布局代码:
<android.support.v4.widget.SwipeRefreshLayout
android:id="@+id/pager_refresh_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingTop="@dimen/tab_height">
<android.support.v4.view.ViewPager
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
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);
}
您必须扩展 FragmentPagerAdapter
或 FragmentStatePagerAdapter
才能轻松嵌入 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_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="@+id/categoryList"
android:scrollbars="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</android.support.v4.widget.SwipeRefreshLayout>
并创建额外的片段 class,这将扩充该布局并实现您需要更新刷新指示器状态的方法。
这里有一个有点老的例子:
http://developer.android.com/training/implementing-navigation/lateral.html
如果你想将你的 ViewPager 与新的支持库 TabLayout 连接起来,它很容易与:
tabLayout.setupWithViewPager(viewPager);
最后,如果您要更新 "fragmented" 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
class 必须实施 getTitle()
方法。
我正在尝试让它工作:我基本上想要在一个 ViewPager 中包含两个 Recyclerview。我遵循了本教程:http://android-java-development.blogspot.de/2012/05/system.html,但它似乎不起作用。我看起来 view pager 是空的,recycler view 没有显示。
这是我的布局代码:
<android.support.v4.widget.SwipeRefreshLayout
android:id="@+id/pager_refresh_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingTop="@dimen/tab_height">
<android.support.v4.view.ViewPager
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
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);
}
您必须扩展 FragmentPagerAdapter
或 FragmentStatePagerAdapter
才能轻松嵌入 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_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="@+id/categoryList"
android:scrollbars="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</android.support.v4.widget.SwipeRefreshLayout>
并创建额外的片段 class,这将扩充该布局并实现您需要更新刷新指示器状态的方法。
这里有一个有点老的例子: http://developer.android.com/training/implementing-navigation/lateral.html
如果你想将你的 ViewPager 与新的支持库 TabLayout 连接起来,它很容易与:
tabLayout.setupWithViewPager(viewPager);
最后,如果您要更新 "fragmented" 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
class 必须实施 getTitle()
方法。