📜  圆角imageview android (1)

📅  最后修改于: 2023-12-03 15:23:05.834000             🧑  作者: Mango

实现圆角ImageView的三种方法

在Android开发中,ImageView是非常常用的控件。但是在某些情况下,我们可能需要将ImageView的四个角变成圆角。本文将介绍三种实现圆角ImageView的方法,分别是:

1.使用BitmapShader+Canvas绘制

public class RoundImageView extends ImageView {

    private Paint mPaint;
    private Path mPath;
    private int mRadius = 10;//默认圆角大小

    public RoundImageView(Context context) {
        this(context, null);
    }

    public RoundImageView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public RoundImageView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPath = new Path();
        //获取属性
        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.RoundImageView);
        mRadius = ta.getDimensionPixelSize(R.styleable.RoundImageView_radius, mRadius);
        ta.recycle();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        Drawable drawable = getDrawable();
        if (drawable == null) {
            super.onDraw(canvas);
            return;
        }
        //先把图片画上
        Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap();
        mPaint.setShader(new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP));
        canvas.save();
        //画圆角
        getRoundPath(getWidth(), getHeight(), mPath, mRadius);
        canvas.drawPath(mPath, mPaint);
        canvas.restore();
    }

    private void getRoundPath(int width, int height, Path path, int radius) {
        path.reset();
        path.addRoundRect(new RectF(0, 0, width, height), radius, radius, Path.Direction.CW);
    }

    public void setRadius(int radius) {
        mRadius = radius;
        invalidate();
    }
}

这种方法的原理是通过将ImageView的drawable转成bitmap,并使用BitmapShader来绘制圆角。这种方法比较简单,但是不支持xml属性设置,也不支持边框等其他特性。

2.使用ClipPath裁剪

public class RoundImageView extends ImageView {

    private Path mPath;
    private int mRadius = 10;//默认圆角大小

    public RoundImageView(Context context) {
        this(context, null);
    }

    public RoundImageView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public RoundImageView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        mPath = new Path();
        //获取属性
        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.RoundImageView);
        mRadius = ta.getDimensionPixelSize(R.styleable.RoundImageView_radius, mRadius);
        ta.recycle();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        Drawable drawable = getDrawable();
        if (drawable == null) {
            super.onDraw(canvas);
            return;
        }
        canvas.save();
        //画圆角
        getRoundPath(getWidth(), getHeight(), mPath, mRadius);
        canvas.clipPath(mPath);
        //先把图片画上
        super.onDraw(canvas);
        canvas.restore();
    }

    private void getRoundPath(int width, int height, Path path, int radius) {
        path.reset();
        path.addRoundRect(new RectF(0, 0, width, height), radius, radius, Path.Direction.CW);
    }

    public void setRadius(int radius) {
        mRadius = radius;
        invalidate();
    }
}

这种方法的原理是通过ClipPath裁剪出圆角矩形区域,从而达到圆角效果。这种方法可以支持xml属性设置,但是对于一些特殊情况,如边框,阴影等效果不支持。

3.使用RoundRectShape和ShapeDrawable

public class RoundImageView extends androidx.appcompat.widget.AppCompatImageView {

    private ShapeDrawable mShapeDrawable;
    private int mRadius = 10;//默认圆角大小

    public RoundImageView(Context context) {
        this(context, null);
    }

    public RoundImageView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public RoundImageView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        //获取属性
        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.RoundImageView);
        mRadius = ta.getDimensionPixelSize(R.styleable.RoundImageView_radius, mRadius);
        ta.recycle();
        mShapeDrawable = new ShapeDrawable(new RoundRectShape(new float[]{mRadius, mRadius, mRadius, mRadius, mRadius, mRadius, mRadius, mRadius}, null, null));
        setBackground(mShapeDrawable);
    }

    public void setRadius(int radius) {
        mRadius = radius;
        mShapeDrawable.setShape(new RoundRectShape(new float[]{mRadius, mRadius, mRadius, mRadius, mRadius, mRadius, mRadius, mRadius}, null, null));
    }
}

这种方法的原理是通过ShapeDrawable和RoundRectShape设置圆角矩形。这种方法可以支持xml属性设置,也可以支持边框,阴影等其他特性。

总结:

三种方法都能完成圆角ImageView的效果,选择哪种方法,就要看具体的需求了。

1.如果要求简单,只是简单的圆角效果,可以选择第一种方法。

2.如果要求支持xml属性设置,可以选择第二种方法。

3.如果要求支持其他特性,如边框,阴影等效果,可以选择第三种方法。

如果有特殊需求,可以自己去扩展。