Currently, I need to use paddingTop
and paddingBottom
of RecyclerView
, as I want to avoid complex space calculation, in my first RecyclerView
item and last item.
However, I notice that, requiresFadingEdge
effect will be affected as well.
This is my XML
<androidx.recyclerview.widget.RecyclerView
android:requiresFadingEdge="vertical"
android:paddingTop="0dp"
android:paddingBottom="0dp"
android:overScrollMode="always"
android:background="?attr/recyclerViewBackground"
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false" />
As you can see, the fading effect shift down by 40dp, which is not what I want.
Fading effect looks fine. But, I need to have non-zero paddingTop
and paddingBottom
, for my RecyclerView
.
Is there a way to make RecyclerView
's requiresFadingEdge
unaffected by paddingTop
and paddingBottom
?
I found the best and kind of official solution for this. Override this 3 methods of RecyclerView
. Which play most important role for fading edge.
First create your recyclerView.
public class MyRecyclerView extends RecyclerView {
// ... required constructor
@Override
protected boolean isPaddingOffsetRequired() {
return true;
}
@Override
protected int getTopPaddingOffset() {
return -getPaddingTop();
}
@Override
protected int getBottomPaddingOffset() {
return getPaddingBottom();
}
}
That's it. Use this recyclerview and you will see fadding edge unaffected.
Following content is just for explanation. If you want to know behind the scene.
To understand how this edge effect is working I dig into the class where android:requiresFadingEdge
is used, And I found that it's not handled by RecyclerView
instead It's handled by View
class which is parent for all view.
In onDraw
method of View
class I found the code for drawing fade edge by using help of this method isPaddingOffsetRequired
. Which used only for handling the fade effect.
According to documentation this method should be overridden by child class If you want to change the behaviour of fading edge. Bydefault It return false
. So By returning true
we are asking view to apply some offset for edge at the time of view drawing.
Look following snippet of onDraw
method of View
class to understand the calculation.
final boolean offsetRequired = isPaddingOffsetRequired();
if (offsetRequired) {
paddingLeft += getLeftPaddingOffset();
}
int left = mScrollX + paddingLeft;
int right = left + mRight - mLeft - mPaddingRight - paddingLeft;
int top = mScrollY + getFadeTop(offsetRequired);
int bottom = top + getFadeHeight(offsetRequired);
if (offsetRequired) {
right += getRightPaddingOffset();
bottom += getBottomPaddingOffset();
}
As we can see top
variable is initialize using getFadeTop(offsetRequired)
.
protected int getFadeTop(boolean offsetRequired) {
int top = mPaddingTop;
if (offsetRequired) top += getTopPaddingOffset();
return top;
}
In this method, top
is calculated by adding value of topOffSet when offset is needed. So to reverse the effect we need to pass negative value of padding which you are passing. so we need to return -getPaddingTop()
.
Now for bottom we are not passing negative value because bottom is working on top + height
. So passing negative value make fade more shorter from the bottom so we need to add bottom padding to make it proper visible.
You can override this 4 method to play with it. getLeftPaddingOffset(), getRightPaddingOffset(), getTopPaddingOffset(), getBottomPaddingOffset()
There are many ways to achieve that but I preferred below solution that works for me.
You can use a third-party library called Android-FadingEdgeLayout
checkout here
Here is a dependency.
implementation 'com.github.bosphere.android-fadingedgelayout:fadingedgelayout:1.0.0'
In yours.xml
<com.bosphere.fadingedgelayout.FadingEdgeLayout
android:id="@+id/fading_edge_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:fel_edge="top|left|bottom|right"
app:fel_size_top="40dp"
app:fel_size_bottom="40dp"
app:fel_size_left="0dp"
app:fel_size_right="0dp">
<androidx.recyclerview.widget.RecyclerView
android:paddingTop="0dp"
android:paddingBottom="0dp"
android:overScrollMode="always"
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false" />
</com.bosphere.fadingedgelayout.FadingEdgeLayout>
Change your ReacyclerView
property according to your need. below is example image with all sided sades. I hope that will help you.
Credits Android-FadingEdgeLayout
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