I have a RecyclerView
inside a ViewPager
that only occupies the bottom half of the screen, and what I want to do is have the entire screen scroll if the RecyclerView
s received a vertical scroll event.
UI hierarchy in a nutshell:
CoordinatorLayout
--- AppBarLayout
--- Toolbar
--- Bunch of static LinearLayouts, occupy most of screen
--- TabLayout
--- ViewPager
--- Fragments with RecyclerView
What I have:
To my understanding, a RecyclerView
is memory-efficient and tries to fit itself in whatever space is available in the screen. In my app, I have a ViewPager
hosting multiple tabs, each of which have a RecyclerView
to display different things.
Could you please give me some ideas of what I could do to make the whole screen scroll? I'm guessing the best shot is to add a CollapsingToolbarLayout
with parallax to the static content in the middle of the screen. I even tried to do this, but the UI was completely broken. It's difficult since I only want the content in the middle of the screen to scroll out, not the toolbars on top. I didn't have much luck with a NestedScrollView
either, apparently its compatibility with ViewPager
and CoordinatorLayout
is not straight-forward..
What I want:
Main Activity Layout:
<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:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
>
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar_contributor"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:focusableInTouchMode="true">
<android.support.v7.widget.SearchView
android:id="@+id/searchview_contributor"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:icon="@drawable/ic_search_white_24dp"
app:defaultQueryHint="Bla bla"
app:iconifiedByDefault="false"/>
<ImageButton
android:layout_width="24dp"
android:layout_height="24dp"
android:background="@android:color/transparent"
android:src="@drawable/ic_person_outline_black_24dp"/>
</android.support.v7.widget.Toolbar>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight=".5"
android:text="La Bla"/>
<Button
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight=".5"
android:text="Bla Bla"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="vertical"
>
<!-- Bunch of stuff, but irrelevant -->
<android.support.design.widget.TabLayout
android:id="@+id/tablayout_profile"
android:layout_width="match_parent"
android:layout_height="40dp"/>
</LinearLayout>
<android.support.v4.view.ViewPager
android:id="@+id/viewpager_profile"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
</android.support.design.widget.AppBarLayout>
</android.support.design.widget.CoordinatorLayout>
The fragment inside the Viewpager:
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerview_photos"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
Thanks in advance!
Update: The responses I received here (for which I am thankful) came a bit too late. If anyone knows which is the correct answer, please let me know!
public class CustomRecyclerView extends RecyclerView {
public CustomRecyclerView(Context context) {
super(context);
}
public CustomRecyclerView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomRecyclerView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
int lastEvent = -1;
boolean isLastEventIntercepted = false;
private float xDistance, yDistance, lastX, lastY;
@Override
public boolean onInterceptTouchEvent(MotionEvent e) {
switch (e.getAction()) {
case MotionEvent.ACTION_DOWN:
xDistance = yDistance = 0f;
lastX = e.getX();
lastY = e.getY();
break;
case MotionEvent.ACTION_MOVE:
final float curX = e.getX();
final float curY = e.getY();
xDistance += Math.abs(curX - lastX);
yDistance += Math.abs(curY - lastY);
lastX = curX;
lastY = curY;
if (isLastEventIntercepted && lastEvent == MotionEvent.ACTION_MOVE) {
return false;
}
if (xDistance > yDistance) {
isLastEventIntercepted = true;
lastEvent = MotionEvent.ACTION_MOVE;
return false;
}
}
lastEvent = e.getAction();
isLastEventIntercepted = false;
return super.onInterceptTouchEvent(e);
}
}
Just change your recyclerview by this .
I've done something very similar to this with a CollapsingToolbarLayout
.
The trick here is to have two toolbars, one at the top with the searchview and another that is the toolbar dedicated to the collapsing layout.
Your searchview toolbar will have app:collapseMode="pin"
.
Your button bar will have app:collapseMode="pin"
.
Your LinearLayout below the button bar will have the default collapse mode so it will scroll. You can even give it a parallax effect with app:collapseMode="parallax"
.
Your TabLayout
will have app:collapseMode="pin"
so it scrolls up under the button bar and pins there.
Your ViewPager
should be outside the CollapsingToolbarLayout
and have the attribute app:layout_behavior="@string/appbar_scrolling_view_behavior"
.
The CollapsingToolbarLayout
will want to display a title. Just call setTitle(null)
on the collapsing toolbar and set your real title on the searchview toolbar.
You can put your navigation and menus on either the searchview toolbar and the collapsing toolbar and they should work as expected.
I will post some XML later; I just wanted to get this answer started.
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