Reputation: 1794
I want to use Android design support library to implement the following UI:
NavigationView
for section navigation.Fragment
will be swapped into the container space (FrameLayout
).Fragment
is always a CoordinatorLayout
. In the layout, a ViewPager
may be used. (*problem)ViewPager
is used for the (parent) Fragment
, it will almost always accompanied by multiple child Fragment
with RecyclerView
. (*problem)ViewPager
, it doesn't swipe properly (eg. not 1 page per swipe).In Activity
, there is a DrawerLayout
with NavigationView
and a FrameLayout
for content fixing as follows:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:openDrawer="start">
<FrameLayout
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true" />
<android.support.design.widget.NavigationView
android:id="@+id/nav_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:fitsSystemWindows="true"
app:headerLayout="@layout/nav_header_main"
app:menu="@menu/activity_main_drawer" />
</android.support.v4.widget.DrawerLayout>
Every time when a navigation item (section) is selected, new (parent) fragment is swapped into FrameLayout (R.id.container)
with the following code:
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.container, new ParentFragment())
.commit();
In parent fragment, CoordinatorLayout
is used together with AppBarLayout
and ViewPager
as follows:
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context="com.test.nestedviewpager.MainActivity">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="@style/AppTheme.PopupOverlay" />
<android.support.design.widget.TabLayout
android:id="@+id/tab_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</android.support.design.widget.AppBarLayout>
<android.support.v4.view.ViewPager
android:id="@+id/view_pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true" />
</android.support.design.widget.CoordinatorLayout>
The code below initializes the ParentFragment
with random number of pages.
package com.test.nestedviewpager;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.design.widget.TabLayout;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
public class ParentFragment extends Fragment {
private static final int MAX_PAGE_COUNT = 5;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater,
@Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.fragment_parent, container, false);
AppCompatActivity activity = (AppCompatActivity) getActivity();
activity.setSupportActionBar((Toolbar) root.findViewById(R.id.toolbar));
final ActionBar actionBar = activity.getSupportActionBar();
if (actionBar != null) {
actionBar.setHomeAsUpIndicator(R.drawable.ic_menu);
actionBar.setDisplayHomeAsUpEnabled(true);
}
ViewPager viewPager = (ViewPager) root.findViewById(R.id.view_pager);
viewPager.setAdapter(new MyPagerAdapter(activity.getSupportFragmentManager(), generatePages()));
TabLayout tabLayout = (TabLayout) root.findViewById(R.id.tab_layout);
tabLayout.setupWithViewPager(viewPager, true);
return root;
}
private static Page[] generatePages() {
Random rng = new Random();
int size = rng.nextInt(MAX_PAGE_COUNT);
if (size <=0 ) { size = 1; }
Page[] pages = new Page[size];
for (int pos = 0; pos < size; pos++) {
pages[pos] = new Page("Page " + (pos + 1));
}
return pages;
}
private static class MyPagerAdapter extends FragmentPagerAdapter {
private final List<Page> mPageList = new ArrayList<>();
MyPagerAdapter(FragmentManager fm, Page[] pages) {
super(fm);
if ((pages != null) && (pages.length > 0)) {
mPageList.addAll(Arrays.asList(pages));
}
}
@Override
public int getCount() {
return mPageList.size();
}
@Override
public Fragment getItem(int position) {
return new ChildFragment();
}
@Override
public CharSequence getPageTitle(int position) {
return mPageList.get(position).title;
}
}
private static class Page {
final String title;
Page(String title) {
this.title = title;
}
}
}
In each child fragment, there consists of a RecyclerView
as follows:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
The code below initializes the ChildFragment
with random number of items.
package com.test.nestedviewpager;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
public class ChildFragment extends Fragment {
private static final int MAX_ITEM_COUNT = 15;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater,
@Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.fragment_child, container, false);
RecyclerView recyclerView = (RecyclerView) root.findViewById(R.id.recycler_view);
recyclerView.setAdapter(new MyRecyclerAdapter(generateItems()));
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
return root;
}
private static Item[] generateItems() {
Random rng = new Random();
final int size = rng.nextInt(MAX_ITEM_COUNT);
if (size > 0) {
Item[] items = new Item[size];
for (int pos = 0; pos < size; pos++) {
items[pos] = new Item("Item " + (pos + 1));
}
return items;
}
return null;
}
private static class MyRecyclerAdapter extends RecyclerView.Adapter<MyRecyclerAdapter.MyViewHolder> {
private final List<Item> mItemList = new ArrayList<>();
MyRecyclerAdapter(Item[] items) {
if ((items != null) && (items.length > 0)) {
mItemList.addAll(Arrays.asList(items));
}
}
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
View itemView = inflater.inflate(R.layout.recycler_item, parent, false);
return new MyViewHolder(itemView);
}
@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
holder.bind(mItemList.get(position));
}
@Override
public int getItemCount() {
return mItemList.size();
}
static class MyViewHolder extends RecyclerView.ViewHolder {
private TextView mTitleView;
MyViewHolder(View itemView) {
super(itemView);
mTitleView = (TextView) itemView.findViewById(R.id.content);
}
void bind(Item item) {
mTitleView.setText(item.title);
}
}
}
private static class Item {
final String title;
Item(String title) {
this.title = title;
}
}
}
I couldn't understand what is wrong with the code written at all. Any help would be very much appreciated.
Thank you.
Upvotes: 4
Views: 4636
Reputation: 191725
I can't see a reason why the ViewPager would be skipping swipes, but for the Child Fragments, you should return root
instead of the super call. That would explain why you see nothing
Maybe instead of activity.getSupportFragmentManager()
try to use getChildFragmentManager()
from the Fragment class
Upvotes: 1