有没有办法让RecyclerView的requiresFadingEdge不受paddingTop和paddingBottom影响

问题描述 投票:0回答:4

目前,我需要在第一个

paddingTop
项和最后一项中使用
paddingBottom
RecyclerView
RecyclerView
,因为我想避免复杂的空间计算。

但是,我注意到,

requiresFadingEdge
效果也会受到影响。

这是我的 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" />

当paddingTop和paddingBottom为40dp时

如你所见,淡入淡出效果下移了40dp,这不是我想要的。


当paddingTop和paddingBottom为0dp时

褪色效果看起来不错。但是,对于我的

paddingTop
,我需要非零
paddingBottom
RecyclerView


有没有办法让

RecyclerView
requiresFadingEdge
不受
paddingTop
paddingBottom
的影响?

android android-recyclerview
4个回答
39
投票

我找到了最好的官方解决方案。重写

RecyclerView
的这 3 个方法。其中对于边缘褪色起着最重要的作用。

首先创建你的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();
    }
}

就是这样。使用此回收器视图,您将看到褪色边缘不受影响。

以下内容仅供说明。如果你想了解幕后故事。

为了了解这种边缘效应是如何工作的,我深入研究了使用

android:requiresFadingEdge
的类,我发现它不是由
RecyclerView
处理的,而是由
View
类处理,该类是所有视图的父级。

onDraw
类的
View
方法中,我找到了使用此方法
isPaddingOffsetRequired
的帮助来绘制淡入淡出边缘的代码。仅用于处理淡入淡出效果。

根据文档,如果您想更改淡入淡出边缘的行为,则应由子类重写此方法。默认返回

false
。因此,通过返回
true
,我们要求视图在绘制视图时为边缘应用一些偏移量。

查看以下

onDraw
类的
View
方法片段以了解计算。

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();
}

正如我们所见,

top
变量是使用
getFadeTop(offsetRequired)
初始化的。

protected int getFadeTop(boolean offsetRequired) {
    int top = mPaddingTop;
    if (offsetRequired) top += getTopPaddingOffset();
    return top;
}

在此方法中,当需要偏移时,通过添加topOffSet的值来计算

top
。因此,为了扭转效果,我们需要传递您正在传递的填充的负值。所以我们需要返回
-getPaddingTop()

现在对于底部,我们不会传递负值,因为底部正在处理

top + height
。因此,传递负值会使淡入淡出距离底部更短,因此我们需要添加底部填充以使其正确可见。

你可以重写这4个方法来玩它。

getLeftPaddingOffset(), getRightPaddingOffset(), getTopPaddingOffset(), getBottomPaddingOffset()


2
投票

我建议一些解决方案 ,希望对你有帮助

1-RecyclerView.ItemDecoration(保留

requiresFadingEdge

class ItemDecoration(private val spacing: Int) : RecyclerView.ItemDecoration(){

   override fun getItemOffsets(outRect: Rect, view: View, parent: 
   RecyclerView, state: RecyclerView.State?) {

   val position = parent.getChildAdapterPosition(view)
   when(position)
    0 ->                          { outRect.top    = spacing /*40dp*/ }
    parent.adapter.itemCount-1 -> { outRect.bottom = spacing /*40dp*/ }

}

2-多个ViewHolder(取决于ViewHolder保留或删除

requiresFadingEdge
https://stackoverflow.com/a/26245463/5255963

3-渐变(删除

requiresFadingEdge

使用可绘制对象制作两个渐变,如下所示:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<gradient
    android:type="linear"
    android:angle="90"
    android:startColor="#000"
    android:endColor="#FFF" />
</shape>

并将

background
设置为 Recyclerview 顶部和底部的两个视图。


1
投票

有很多方法可以实现这一目标,但我更喜欢下面适合我的解决方案。 您可以使用名为

Android-FadingEdgeLayout
checkout here

的第三方库

这是一个依赖项。

implementation 'com.github.bosphere.android-fadingedgelayout:fadingedgelayout:1.0.0'

在你的.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>

根据您的需要更改您的

ReacyclerView
属性。下面是带有所有侧面的示例图像。我希望这对你有帮助。

致谢Android-FadingEdgeLayout


0
投票

一些简单的解决方法对我有用。 由于我不想扩展或导入更多库,因此我用 LinearLayout 包装了 RecyclerView。

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingTop="[some #]dp"
    android:paddingBottom="[some #]dp">

    <androidx.recyclerview.widget.RecyclerView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fadingEdgeLength="[some #]"
        android:requiresFadingEdge="vertical"/>

</LinearLayout>

环绕线性布局的宽度和高度可以是任意的。

© www.soinside.com 2019 - 2024. All rights reserved.