Recyclerview单条目沿圆弧移动

现在AI这么火热,优化也方便,这里问了文心一言,如果着急用直接拿走用不用看细节,毕竟我也没看细节,直接看的效果,哈哈

public class MatrixTranslateLayout extends LinearLayout {
    private int parentHeight = 0;
    private int topOffset = 0;
    public MatrixTranslateLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public void setParentHeight(int height) {
        parentHeight = height;
    }

    @Override
    protected void dispatchDraw(Canvas canvas) {
        canvas.save();
        if (topOffset == 0) {
            topOffset = getHeight() / 2;
        }
        int top = getTop()+topOffset;
        Log.e("11111",top+":"+parentHeight);

       float tran = calculateTranslate(top , parentHeight);

        Matrix m = canvas.getMatrix();
        //tran水平平移量
        m.setTranslate(tran,0);
        canvas.concat(m);
        super.dispatchDraw(canvas);
        canvas.restore();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }
   /* private float calculateTranslate(int top, int h) {
        if (h == 0) return 0f; // 避免除以0

        int centerY = h / 2;
        float distanceFromCenter = top - centerY; // 计算与中心的距离

        // 1. 取绝对值,确保只向右平移(不关心方向)
        float absDistance = Math.abs(distanceFromCenter);

        // 2. 归一化到 [0, 1] 范围(h/2 是最大可能距离)
        float normalizedDistance = Math.min(absDistance / (h / 2f), 1f);

        // 3. 使用平滑曲线(如三次方函数)使平移更自然
        float smoothFactor = (float) Math.pow(normalizedDistance, 1.5f); // 1.5 次方使变化更平缓

        // 4. 计算最大平移量(例如视口宽度的 30%)
        //如果觉得平移不够明显,可以调整 maxTranslate   0.5f
        float maxTranslate = getWidth() * 0.3f;

        // 5. 最终平移量(始终 ≥ 0,确保只向右移动)
        return smoothFactor * maxTranslate;
    }*/

    /**
     * 定版是这个,上面的方法也可以
     */
    private float calculateTranslate(int top, int h) {
        if (parentHeight == 0) return 0f;

        float centerY = parentHeight / 2f;
        float maxDistance = parentHeight / 2f;
        float normalizedDistance = (top - centerY) / maxDistance; // [-1, 1]

        // θ 范围 [0, π](半圆)
        float theta = (float) ((normalizedDistance + 1) * Math.PI / 2); // [0, π]

        float radius = getWidth() * 0.4f;
        // 计算半圆轨迹的 x 偏移量
        float xOffset = (float) (radius * Math.sin(theta)); // 0 ≤ x ≤ 2r

        // 调整偏移量(可选)
        xOffset = Math.abs(xOffset - radius); // 使 x 范围在 [-r, r]

        return xOffset;
    }
}

xOffset = Math.abs(xOffset - radius); // 使 x 范围在 [-r, r]

这里取了绝对值,如果不取绝对值就会呈现S滑动,我这里转盘在右边所以右移都是正直

如果往左移就取负值,最后的xOffse*-1即可

使用也简单,在Recyclerview单条布局最外层用

MatrixTranslateLayout包裹就行了
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

csdn_zxw

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值