I'm trying to get this working: I basically want two Recyclerviews in one ViewPager. I followed this Tutorial: http://android-java-development.blogspot.de/2012/05/system.html, but it doesn't seem to work. I looks like the view pager is empty and the recycler view doesn't show up.
Here's my layout code:
<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>
And my 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);
}
}
And my onCreatView method:
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);
Here I'm passing the cursor object to the adapter:
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
((NewsAdapter) newsPagerAdapter.getAdapterForViewAtIndex(0)).swapCursor(data);
}
Since ViewPager2 makes use of RecyclerView as adapter to show items we can customize it's performance and design in many ways. We can make use of DiffUtils, layout direction such as right-to left, both vertical and horizontal direction to show items, PageTransformations etc.
This function is deprecated.
RecyclerView makes it easy to efficiently display large sets of data. You supply the data and define how each item looks, and the RecyclerView library dynamically creates the elements when they're needed. As the name implies, RecyclerView recycles those individual elements.
You have to extend FragmentPagerAdapter
or FragmentStatePagerAdapter
in order to easily embed RecyclerView. If you are going to update your ViewPager contents during its lifecycle it is strictly recommended to use FragmentStatePagerAdapter
You will have to create additional fragment layout, containing RecyclerView
.
If you wish to update your ViewPager
with SwipeRefreshLayout
, don't wrap it with SwipeRefreshLayout
. Instead, you must have SwipeRefreshLayout
inside fragment layout.
Therefore for your fragment you may get the following 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>
And create additional Fragment class, which will inflate that layout and implement methods, that you will need to update refresh indicator status.
A bit old example is found here: http://developer.android.com/training/implementing-navigation/lateral.html
If you wish to connect your ViewPager with new support library TabLayout, it is easily one with:
tabLayout.setupWithViewPager(viewPager);
Finally, if you will update your "fragmented" ViewPager
, don't try to reset the adapter, as fragments are managed not with adapter, but with FragmentManager
. It is wiser to update content of corresponding 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();
}
}
Your MyFragment
class has to implement getTitle()
method.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With