I'm trying to create a RecyclerView with scrolling background, like the one shown below. The idea is, as I scroll up/down the viewholders, the background (light-green) image should also move up/down in sync. Any clue as to how to accomplish this?
Here is my basic RecyclerView configuration
<android.support.v7.widget.RecyclerView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="@dimen/item_margin"
android:clipToPadding="false"
android:background="@drawable/ic_light_green_image"/>
I had the same use-case -- scrolling a list of cards that lies above the app bar along the Z axis, just like Google Play Music. It's actually pretty simple, but the documentation for RecyclerView#computeVerticalScrollOffset()
is completely misleading. It doesn't calculate the scrollbar thumb's offset, instead it calculates by how much the RecyclerView
itself has scrolled (which is exactly what we need here).
mPostList.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
int scrollY = mPostList.computeVerticalScrollOffset();
// mAppBarBg corresponds to your light green background view
mAppBarBg.setTranslationY(-scrollY);
// I also have a drop shadow on the Toolbar, this removes the
// shadow when the list is scrolled to the top
mToolbarCard.setCardElevation(scrollY <= 0 ? 0 : toolbarElevation);
}
});
My layout looks like this, if it helps:
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- this corresponds to your light green background -->
<FrameLayout
android:id="@+id/app_bar_bg"
android:layout_width="match_parent"
android:layout_height="@dimen/toolbar_container_height"
android:background="@color/primary" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<!-- CardView adds a drop shadow to the Toolbar -->
<android.support.v7.widget.CardView
android:id="@+id/toolbar_card"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardCornerRadius="0dp">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" />
</android.support.v7.widget.CardView>
<android.support.v7.widget.RecyclerView
android:id="@+id/post_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
android:scrollbarStyle="outsideOverlay"
android:scrollbars="vertical" />
</LinearLayout>
</FrameLayout>
Hope this helps!
I probably wouldn't use the background of the RecyclerView for the actual thing that moves. Maybe don't put a background on the RecyclerView and instead of a different view that is behind the RecyclerView that actually moves. Then you could override onDraw or onLayout on the RecyclerView and update the position of your background to wherever you want it to be relative to the scroll percentage of the RecyclerView.
Something like this... XML:
<RelativeLayout ...>
<SomeBackgroundView id="backgroundView" ...>
<MyRecyclerView ...>
</RelativeLayout>
Code:
class MyRecyclerView extends RecyclerView {
protected int mLastScroll = Integer.MAX_VALUE;
protected ScrollChangedListener mScrollChangedListener;
// ...
@Override
void onDraw(Canvas c) {
int scrollY = getScrollY();
if (scrollY != mLastScroll) {
mLastScroll = scrollY;
if (mScrollChangedListener!= null)
mScrollChangedListener.onScrollChanged(scrollY);
}
super.onDraw(c);
}
public void setScrollChangedListener(ScrollChangedListener listener) {
mScrollChangedListener = listener;
}
public interface ScrollChangedListener {
void onScrollChanged(int newScroll);
}
}
class SomeActivity extends Activity implements ScrollChangedListener {
// ...
@Override
void onScrollChanged(int newScroll) {
// Set the background view's position based on newScroll
}
}
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