CrimzonWeb
CrimzonWeb

Reputation: 171

Recyclerview elevation progressively changes when scrolling

I have a recyclerview, which i've added a elevation to. It seems that elevation gets higher depending on where on the screen the item is located vertically, the shadow grows as the item gets scrolled down. I've tried adding a background color, which has not helped. I found another post with a video showing the problem. https://youtu.be/nROYq8rpUMs

Here's my relativelayout where I add the elevation.

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="#EDEDED"
    android:focusable="?attr/selectableItemBackground"
    android:layout_marginTop="15dp"
    android:layout_marginBottom="15dp"
    android:paddingTop="10dp"
    android:paddingBottom="10dp"
    android:id="@+id/newsRowRelativeLayout"
    android:elevation="4dp">

    <ImageView
        android:id="@+id/newsImage"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:maxHeight="300dp"
        android:layout_marginTop="5dp"
        android:layout_marginBottom="15dp"
        android:scaleType="centerCrop"
        android:adjustViewBounds="true"
        android:background="@color/mainTextBGColor" />

    <TextView
        android:id="@+id/newsTitle"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@android:color/transparent"
        android:layout_below="@id/newsType"
        android:textStyle="bold"
        android:textColor="@color/news_title"
        android:paddingLeft="@dimen/activity_margin"
        android:paddingRight="@dimen/activity_margin"
        android:textSize="@dimen/news_title_main" />

    <TextView
        android:id="@+id/newsType"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@android:color/transparent"
        android:layout_below="@id/newsImage"
        android:textStyle="bold"
        android:textAllCaps="true"
        android:layout_marginTop="5dp"
        android:layout_marginBottom="10dp"
        android:textColor="@color/mainBGColor"
        android:paddingLeft="@dimen/activity_margin"
        android:paddingRight="@dimen/activity_margin"
        android:textSize="@dimen/news_tag_detailed" />

    <TextView
        android:id="@+id/newsText"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/newsTitle"
        android:background="@android:color/transparent"
        android:ellipsize="end"
        android:maxLines="3"
        android:textColor="@color/news_text"
        android:layout_marginTop="10dp"
        android:layout_marginBottom="5dp"
        android:paddingLeft="@dimen/activity_margin"
        android:paddingRight="@dimen/activity_margin"
        android:textSize="@dimen/news_text_main"/>

</RelativeLayout>

Upvotes: 1

Views: 934

Answers (2)

Dario Ambrosini
Dario Ambrosini

Reputation: 46

I'm not posting the final solution, but the draft I'm working on.

I understand the theory of Android's elevation, but it doesn't make any sense to me, so my idea is to listen the scroll of the contents on screen and adapt the elevation based on that.

public class VerticalScrollListener extends RecyclerView.OnScrollListener {

@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
    super.onScrolled(recyclerView, dx, dy);

    int[] visible = new int[1];
    mLayoutManager.findFirstVisibleItemPositions(visible);
    int[] lastvisible = new int[1];
    mLayoutManager.findLastVisibleItemPositions(lastvisible); 
    for (int i = visible[0]; i<lastvisible[0]; i++){
      RecyclerView.ViewHolder viewHolder = recyclerView.findViewHolderForAdapterPosition(i);
     int[] location = new int[2];
     ((MessageViewHolder)viewHolder).contentView.getLocationOnScreen(location);
     float y = location[1];
     float ratio = y/scheight;
     ((MessageViewHolder)viewHolder).contentView.setElevation(16-14*ratio);
    }

}

@Override
public void onScrollStateChanged(final RecyclerView recyclerView, final int newState) {
    super.onScrollStateChanged(recyclerView, newState);
}}

Upvotes: 1

reVerse
reVerse

Reputation: 35254

There's nothing wrong with it. The Elevation effect uses a so called Key-Light and Ambient-Light. One sits right above the screen (Ambient-Light), the other one (Key-Light) with a 45° angle above the screen. That's why the shadow is moving while you're scrolling.

tl;dr The shadow is not static but dynamically calculated. See also the following picture explaining the concept:

material design shadows concept

Upvotes: 2

Related Questions