【问题标题】:Custom ImageView loses transparency as soon as it goes out of screen in recycleView自定义 ImageView 在 recycleView 中离开屏幕后立即失去透明度
【发布时间】:2016-07-21 00:16:32
【问题描述】:

我有一个自定义 ImageView,它覆盖 onDraw 方法以使用 Path 裁剪角以给出给定半径的圆角。我有一个 RecyclerView,我在所有 4 个项目中都有这些自定义 ImageView。现在的问题是这个自定义 ImageView 第一次出现在列表中时渲染得很好。一次只能容纳 2 个屏幕。当我向下滚动时,所有视图中的一切都很好。我可以在所有这些中看到圆角。但是当我向上滚动到上一个项目时。现在这些角落失去了角落的透明度,除了列表中的第三个项目外,其他所有项目都变成黑色。 onDraw 中的画布也有isOpaque = true。我尝试了很多东西,但似乎没有任何效果。这是代码

public class RoundedImageView extends ImageView
{
    private Paint mPaint;
    private int mCornerRadius = 0;
    private boolean mRoundedTopLeft = true, mRoundedBottomLeft = true, mRoundedTopRight = true, mRoundedBottomRight = true;

    public void setCornerRadius(int mCornerRadius)
    {
        this.mCornerRadius = mCornerRadius;
    }

    public void RoundCorners(boolean isRoundedTopLeft, boolean isRoundedTopRight, boolean isRoundedBottomLeft, boolean isRoundedBottomRight)
    {
        mRoundedTopLeft = isRoundedTopLeft;
        mRoundedBottomLeft = isRoundedBottomLeft;
        mRoundedBottomRight = isRoundedBottomRight;
        mRoundedTopRight = isRoundedTopRight;
    }

    public RoundedImageView(Context context)
    {
        super(context);
        if (Build.VERSION.SDK_INT >= 11)
            setLayerType(View.LAYER_TYPE_SOFTWARE, null);
        setupPaint();
    }

    public RoundedImageView(Context context, AttributeSet attrs)
    {
        super(context, attrs);
        if (Build.VERSION.SDK_INT >= 11)
            setLayerType(View.LAYER_TYPE_SOFTWARE, null);
        setupPaint();
    }

    public RoundedImageView(Context context, AttributeSet attrs, int defStyleAttr)
    {
        super(context, attrs, defStyleAttr);
        if (Build.VERSION.SDK_INT >= 11)
            setLayerType(View.LAYER_TYPE_SOFTWARE, null);
        setupPaint();
    }

    @TargetApi(21)
    public RoundedImageView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes)
    {
        super(context, attrs, defStyleAttr, defStyleRes);
        if (Build.VERSION.SDK_INT >= 11)
            setLayerType(View.LAYER_TYPE_SOFTWARE, null);
        setupPaint();

    }

    private Paint setupPaint()
    {
        mPaint = new Paint();
        mPaint.setColor(Color.TRANSPARENT);
        mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
        mPaint.setAntiAlias(true);
        mPaint.setDither(true);
        mPaint.setStrokeWidth(1);
        mPaint.setStrokeJoin(Paint.Join.ROUND);
        mPaint.setStrokeCap(Paint.Cap.ROUND);
        mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
        return mPaint;
    }

    @Override
    protected void onDraw(Canvas canvas)
    {
        super.onDraw(canvas);

        Path path = RoundedRect(0, 0, getWidth(), getHeight(), mCornerRadius, mCornerRadius,
                mRoundedTopLeft, mRoundedTopRight, mRoundedBottomRight, mRoundedBottomLeft);
        canvas.drawPath(path, mPaint);
    }

    public static Path RoundedRect(
            float left, float top, float right, float bottom, float rx, float ry,
            boolean tl, boolean tr, boolean br, boolean bl)
    {
        Path path = new Path();
        if (rx < 0) rx = 0;
        if (ry < 0) ry = 0;
        float width = right - left;
        float height = bottom - top;
        if (rx > width / 2) rx = width / 2;
        if (ry > height / 2) ry = height / 2;
        float widthMinusCorners = (width - (2 * rx));
        float heightMinusCorners = (height - (2 * ry));

        path.moveTo(right, top + ry);
        if (tr)
            path.rQuadTo(0, -ry, -rx, -ry);//top-right corner
        else
        {
            path.rLineTo(0, -ry);
            path.rLineTo(-rx, 0);
        }
        path.rLineTo(-widthMinusCorners, 0);
        if (tl)
            path.rQuadTo(-rx, 0, -rx, ry); //top-left corner
        else
        {
            path.rLineTo(-rx, 0);
            path.rLineTo(0, ry);
        }
        path.rLineTo(0, heightMinusCorners);

        if (bl)
            path.rQuadTo(0, ry, rx, ry);//bottom-left corner
        else
        {
            path.rLineTo(0, ry);
            path.rLineTo(rx, 0);
        }

        path.rLineTo(widthMinusCorners, 0);
        if (br)
            path.rQuadTo(rx, 0, rx, -ry); //bottom-right corner
        else
        {
            path.rLineTo(rx, 0);
            path.rLineTo(0, -ry);
        }

        path.rLineTo(0, -heightMinusCorners);

        path.close();//Given close, last lineto can be removed.

        path.setFillType(Path.FillType.INVERSE_EVEN_ODD);
        return path;
    }
}

我已经尝试过的: - 在 ViewHolder 中设置 isRecyclable false

  • 在绘画中设置不同的 PorterDuff 模式

  • 此视图的LAYER_TYPE_HARDWARE(硬件加速)

  • setDrawingCacheBackgroundColor(0x00000000); 在构造函数中

  • setLayerType(View.LAYER_TYPE_SOFTWARE, paint);在这个函数中传递绘画

  • super.onDraw()之前尝试让画布透明

更新

经过大量摆弄后,我得出结论,每当我的 viewHolder 的视图离开屏幕时。它的所有阿尔法通道变成黑色。我觉得这与setLayerType(View.LAYER_TYPE_SOFTWARE, null); 有关系

【问题讨论】:

  • 你可以在onBindViewHolder中设置attributes,比如radiusopacity
  • @Sanoop 是的,那也很酷,但我想在这样做之前先解决这个问题。
  • 是的..太好了。 .但是尝试在onBindViewHolder 中设置attributes 并检查是否是导致问题的回收器..
  • @Sanoop 不,没用。其实我也试过在ViewHolder中设置setIsRecyclable(false)。还是一样。
  • 是的,正如您所说,尝试在 onBindViewHolder 中设置值。还是一样。我已经写了我尝试过的所有内容。

标签: java android imageview android-canvas


【解决方案1】:

通过加速父软件来工作。

我解决了这个问题

if (Build.VERSION.SDK_INT >= 11)
                view.setLayerType(View.LAYER_TYPE_SOFTWARE, null);

在我的 ViewHolder 的构造函数中。即使我为任何父容器视图启用了软件加速,它也能正常工作。

现在我不知道为什么会这样。

【讨论】:

  • 这是因为在回收器视图中,viewholder 是动态附加的,因此您的视图附加到的父级应该是软件加速的。同样,硬件加速也是如此。
猜你喜欢
  • 1970-01-01
  • 2011-03-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多