将自定义遮罩应用于 ImageView

Apply custom mask to an ImageView

我想像这样调整我的 ImageView:

我尝试了不同的方法,例如通过 xml 使用形状或使用 OutlineProvider。对于这种情况,两者都没有真正起作用。

现在我写了一个 CustomImageView,它画了一个像这样的圆:

class HeaderImageView : AppCompatImageView {

    @SuppressLint("CanvasSize")
    override fun onDraw(canvas: Canvas) {
        val halfWidth = (canvas.width / 2).toFloat()
        val radius = height.toFloat()
        val path = Path().apply {
            addCircle(halfWidth, 0f, radius, Path.Direction.CCW)
        }

        canvas.clipPath(path)

        super.onDraw(canvas)
    }
}

如何操作路径以获得我想要的结果?

谢谢!

编辑:

需要说明的是,我有一张图片我想要 "manipulate",而不是颜色。

已添加 xml:

    <.HeaderImageView
        android:layout_width="match_parent"
        android:layout_height="230dp"
        android:fitsSystemWindows="false"
        android:scaleType="centerCrop"
        android:src="@drawable/bg"
        app:layout_collapseMode="parallax" />

我正在使用路径绘制圆形。 并使用某种机制使图像适合圆形部分。

我用Path做了。检查一下。

public class RoundedView extends AppCompatImageView {
private Bitmap mBitmap;
Path mPath;
float width, height, offset;
float percent = 0.37f;
private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);


public RoundedView(Context context) {
    super(context);
}

public RoundedView(Context context, @Nullable AttributeSet attrs) {
    super(context, attrs);
    init(context, attrs);
}

public RoundedView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    init(context, attrs);
}

private void init(Context context, AttributeSet attrs) {
    TypedArray arr = context.obtainStyledAttributes(attrs, R.styleable.RoundedView);
    percent = arr.getFloat(R.styleable.RoundedView_roundPercent, 0.37f);
    arr.recycle();
}

@Override
protected void onDraw(Canvas canvas) {
    if (mPath != null) {
        canvas.drawPath(mPath, mPaint);
    }
}

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    super.onSizeChanged(w, h, oldw, oldh);
    width = w;
    height = h;

    offset = w / 2f;

    change();

}

private void change() {
    float roundness = percent * height;


    Drawable d = getDrawable();
    if (d != null) {

        mBitmap = drawableToBitmap(d);
        mBitmap = Bitmap.createScaledBitmap(mBitmap, (int) width, (int) height, false);

        final Shader shader = new BitmapShader(mBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
        mPaint.setShader(shader);

        mPath = new Path();
        mPath.moveTo(0, 0);
        mPath.lineTo(width, 0);
        mPath.lineTo(width, height - roundness);
        mPath.quadTo(offset, height + roundness, 0, height - roundness);
        mPath.close();
    }
}

@Override
public void setImageDrawable(@Nullable Drawable drawable) {
    super.setImageDrawable(drawable);

    change();

}

public Bitmap drawableToBitmap(Drawable drawable) {
    Bitmap bitmap = null;

    if (drawable instanceof BitmapDrawable) {
        BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
        if (bitmapDrawable.getBitmap() != null) {
            return bitmapDrawable.getBitmap();
        }
    }

    if (drawable.getIntrinsicWidth() <= 0 || drawable.getIntrinsicHeight() <= 0) {
        bitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888); // Single color bitmap will be created of 1x1 pixel
    } else {
        bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
    }

    Canvas canvas = new Canvas(bitmap);
    drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
    drawable.draw(canvas);
    return bitmap;
}
}

感谢您的回答,这一定会对其他用户有所帮助。 不幸的是,我不得不帮助自己获得想要的结果。

这是我的最终解决方案,它将四边形贝塞尔曲线应用于 ImageView。

class HeaderImageView : AppCompatImageView {
    constructor(context: Context?) : super(context) {
        init()
    }

    constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs) {
        init()
    }

    constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {
        init()
    }

    lateinit var paint: Paint

    private fun init() {
        paint = Paint()
        paint.color = Color.WHITE
        paint.xfermode = PorterDuffXfermode(PorterDuff.Mode.SRC_ATOP)
        paint.style = Paint.Style.FILL
    }

    @SuppressLint("CanvasSize")
    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)

        val fHeight = canvas.height.toFloat()
        val startEndHeight = canvas.height / 1.18f
        val fWidth = canvas.width.toFloat()
        val halfWidth = (fWidth / 2)

        val path = Path()
        //X = Left side, Y = close to bottom
        val ptStart = PointF(0f, startEndHeight)
        //X = Middle, Y = Bottom
        val ptMiddle = PointF(halfWidth, fHeight + 95)
        // X = Right Side, Y = close to bottom
        val ptEnd = PointF(fWidth, startEndHeight)

        path.moveTo(ptStart.x, ptStart.y)
        path.quadTo(ptMiddle.x, ptMiddle.y, ptEnd.x, ptEnd.y)
        path.lineTo(fWidth, fHeight)
        path.lineTo(0f, fHeight)

        path.close()

        canvas.drawPath(path, paint)
    }
}