RecyclerView设置边缘渐变失效

使用android提供的GridLayoutManager、LinearLayoutManagerd,在xml添加fadingEdgeLength和requiresFadingEdge是有渐变效果的。

ini 复制代码
<androidx.recyclerview.widget.RecyclerView
  android:id="@+id/rv"
  android:layout_width="0dp"
  android:layout_height="0dp"
  android:fadingEdgeLength="50dp"
  android:requiresFadingEdge="horizontal"/>

但是用了自定义LayoutManager之后就失效了。


原因

自定义的LayoutManager没有重写computeHorizontalScrollOffset、computeHorizontalScrollRang等方法。

less 复制代码
public int computeHorizontalScrollExtent(@NonNull State state) {
    return 0;
}

public int computeHorizontalScrollOffset(@NonNull State state) {
    return 0;
}

public int computeHorizontalScrollRange(@NonNull State state) {
    return 0;
}

public int computeVerticalScrollExtent(@NonNull State state) {
    return 0;
}

public int computeVerticalScrollOffset(@NonNull State state) {
    return 0;
}

public int computeVerticalScrollRange(@NonNull State state) {
    return 0;
}

渐变效果是在View.draw()中实现的。draw渐变效果时,是分了上下左右,四个方向来绘制的。只要了解了一个方向的渐变效果就一通百通了。

在View绘制渐变效果时,getTopFadingEdgeStrength返回的是0,导致drawTop为false,所以没有渐变效果。

ini 复制代码
public void draw(@NonNull Canvas canvas) {
    final int viewFlags = mViewFlags;

    // 是否设置了requiresFadingEdge
    boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;
    boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;

    boolean drawTop = false;
    float topFadeStrength = 0.0f;

    if (verticalEdges) {
        // 顶部渐变的强度,范围是0~1
        // 最终会调用到LayoutManger.computeVerticalScollOffset,
        // 因为自定义的LayoutManger没有重写该方法,所以返回的是0.
        topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength()));
        // fadeHeight就是在xml中设置的fadingEdgeLength
        // 因为topFadeStrength为0,所以drawTop就为false了
        drawTop = topFadeStrength * fadeHeight > 1.0f;
    }

    saveCount = canvas.getSaveCount();
    int topSaveCount = -1;

    int solidColor = getSolidColor();
    if (solidColor == 0) {
        if (drawTop) {
            topSaveCount = canvas.saveUnclippedLayer(left, top, right, top + length);
        }
    } else {
        scrollabilityCache.setFadeColor(solidColor);
    }

    // 绘制渐变效果
    if (drawTop) {
        matrix.setScale(1, fadeHeight * topFadeStrength);
        matrix.postTranslate(left, top);
        fade.setLocalMatrix(matrix);
        p.setShader(fade);
        if (solidColor == 0) {
            // 和背景颜色一致的渐变效果
            canvas.restoreUnclippedLayer(topSaveCount, p);
        } else {
            // getSolidColor获取到的颜色渐变
            canvas.drawRect(left, top, right, top + length, p);
        }
    }

}

解决

方法一:重写LayoutManger的相关方法,返回对应的值。

方法二:直接重写RecylerView的getBottomFadingEdgeStrength、getLeftFadingEdgeStrength等方法。

csharp 复制代码
protected float getBottomFadingEdgeStrength() {
    return 1f;
}


protected float getLeftFadingEdgeStrength() {
    return 1f;
}


protected float getRightFadingEdgeStrength() {
    return 1f;
}

protected float getTopFadingEdgeStrength() {
    return 1f;
}
相关推荐
方白羽2 小时前
Android APK安全防护
android·安全·apk
小黄人软件2 小时前
AndroidStudio老项目 macOS运行BlueTooth蓝牙串口助手(Android+Studio源码).rar
android·macos
00后程序员张2 小时前
苹果App Store上架指南:费用、原理与步骤详解
android·ios·小程序·https·uni-app·iphone·webview
天神哥哥啊2 小时前
cocos联调注意事项-安卓
android
TDengine (老段)2 小时前
TDengine TSDB 实战排障四(升级与兼容)
android·java·大数据·数据库·物联网·时序数据库·tdengine
蓝速科技3 小时前
政务自助终端信创选型与无人值守落地方案
android·大数据·数据库·人工智能·科技·技术分享·政务
硫酸锌014 小时前
在手机上运行Python增量备份手机数据到PC电脑
android·windows·python
hai_android4 小时前
子 View 被压小时,如何向父容器"告状"?——MEASURED_STATE_TOO_SMALL 向上传递机制
android·kotlin·android jetpack
AFinalStone5 小时前
Android 7 多用户源码解析(七)系统服务的多用户感知处理
android·系统架构·多用户
怪奇云呼军5 小时前
从 ElevenLabs 看工具调用:闪电智能 Voice Agent 的企业集成验收设计
android·大数据·运维·服务器·网络·人工智能·kotlin