I need to make a scrollable fragment with static views at the top and a ViewPager with a RecyclerView in each page at the bottom. I am trying to achieve the desired outcome using a CoordinatorLayout, but ran into a problem - when I fling the top view up (in order to scroll down) and soon after fling RecyclerView down (in order to scroll up), the scrolling is kind of cancelling out and jitters; when I first fling Recycler View down and then the top view up, the whole fragment scrolls back to the top. It looks like the scrolling is carried over and not stopped when I start scrolling in opposite direction.
I found a tutorial with a similar layout (code), but after trying it out, I found out that it suffers from the same issue.
Here are the recordings of the issue:
Edit: added layout code below
fragment_layout.xml
:
<?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"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<android.support.design.widget.AppBarLayout
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
>
<android.support.design.widget.CollapsingToolbarLayout
android:id="@+id/main.collapsing"
android:layout_width="match_parent"
android:layout_height="200dp"
app:expandedTitleMarginStart="48dp"
app:expandedTitleMarginEnd="64dp"
app:layout_scrollFlags="scroll|snap"
>
<ImageView
android:id="@+id/materialup.profile_backdrop"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
android:src="@drawable/picture300x300"
app:layout_collapseMode="parallax"
/>
</android.support.design.widget.CollapsingToolbarLayout>
<android.support.v7.widget.Toolbar
android:id="@+id/materialup.toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="24dp"
app:theme="@style/ThemeOverlay.AppCompat.Light"
app:layout_scrollFlags="scroll|enterAlways|snap"
style="@style/Widget.AppCompat.Toolbar"
/>
<LinearLayout
android:id="@+id/materialup.title_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingTop="8dp"
android:gravity="center"
app:layout_scrollFlags="scroll|enterAlways|snap"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="@style/TextAppearance.AppCompat.Widget.ActionBar.Title"
android:text="Title"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:layout_marginBottom="4dp"
android:textAppearance="@style/TextAppearance.AppCompat.Widget.ActionBar.Subtitle"
android:text="SubTitle"
android:textColor="@android:color/white"
/>
</LinearLayout>
<android.support.design.widget.TabLayout
android:id="@+id/result_tabs"
android:layout_width="fill_parent"
android:layout_height="24dp"
app:tabSelectedTextColor="?android:attr/textColorPrimaryInverse"
app:tabIndicatorColor="?android:attr/textColorPrimaryInverse"
app:tabIndicatorHeight="4dp"
/>
</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"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
/>
MyFragment.java
:
import android.os.Bundle;
import android.support.annotation.NonNull;
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.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.example.ewelina.matador.R;
public class MyFragment extends android.support.v4.app.Fragment {
public static MyFragment newInstance() {
return new MyFragment();
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
}
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
final View rootView = inflater.inflate(R.layout.fragment_layout, container, false);
TabLayout tabLayout = rootView.findViewById(R.id.result_tabs);
ViewPager viewPager = rootView.findViewById(R.id.view_pager);
viewPager.setAdapter(new TabsAdapter(getChildFragmentManager()));
tabLayout.setupWithViewPager(viewPager);
return rootView;
}
private static class TabsAdapter extends FragmentPagerAdapter {
private static final int TAB_COUNT = 2;
TabsAdapter(FragmentManager fm) {
super(fm);
}
@Override
public int getCount() {
return TAB_COUNT;
}
@Override
public Fragment getItem(int i) {
return FakePageFragment.newInstance();
}
@Override
public CharSequence getPageTitle(int position) {
return "Tab " + String.valueOf(position);
}
}
}
FakePageFragment.java
:
public class FakePageFragment extends Fragment {
private RecyclerView mRootView;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
mRootView = (RecyclerView) inflater.inflate(R.layout.fragment_page, container, false);
return mRootView;
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
initRecyclerView();
}
private void initRecyclerView() {
mRootView.setAdapter(new FakePageAdapter(20));
}
public static Fragment newInstance() {
return new FakePageFragment();
}
private static class FakePageAdapter extends RecyclerView.Adapter<FakePageVH> {
private final int numItems;
FakePageAdapter(int numItems) {
this.numItems = numItems;
}
@Override
public FakePageVH onCreateViewHolder(ViewGroup viewGroup, int i) {
View itemView = LayoutInflater.from(viewGroup.getContext())
.inflate(R.layout.list_item_card, viewGroup, false);
return new FakePageVH(itemView);
}
@Override
public void onBindViewHolder(FakePageVH fakePageVH, int i) {
// do nothing
}
@Override
public int getItemCount() {
return numItems;
}
}
private static class FakePageVH extends RecyclerView.ViewHolder {
FakePageVH(View itemView) {
super(itemView);
}
}
}
fragment_page.xml
:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.RecyclerView
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/my_recycler_view"
android:scrollbars="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layoutManager="android.support.v7.widget.LinearLayoutManager"
tools:listitem="@layout/list_item_card"
/>
list_item_card.xml
:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_gravity="center"
android:layout_width="match_parent"
android:layout_height="200dp"
android:layout_marginRight="8dp"
android:layout_marginLeft="8dp"
android:layout_marginBottom="4dp"
android:layout_marginTop="4dp"
>
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fontFamily="sans-serif-light"
android:padding="8dp"
android:text="Lorem ipsum"
android:lineSpacingExtra="4dp"
android:ellipsize="end"
/>
</LinearLayout>