Android 如何将imageview转换为不同的形状?

Android 如何将imageview转换为不同的形状?,android,imageview,android-shapedrawable,Android,Imageview,Android Shapedrawable,实际上我想把图像转换成图片中提到的形状。我在中试过很多类似的问题,所以没有一个是有用的。您可能建议在imageView的前台使用drawable,但我必须以编程方式设置前台,这仅在api>23时有效。谁能帮我解决这个问题 你们可以在图像中看到图像的背景。我想通过编程将图像转换成那个形状 甚至我也尝试使用Gradient Drawable,但都是徒劳的 代码: 您可以通过应用clipPath来更改imageView类的onDraw方法: @Override protected void onDra

实际上我想把图像转换成图片中提到的形状。我在
中试过很多类似的问题,所以
没有一个是有用的。您可能建议在
imageView
的前台使用drawable,但我必须以编程方式设置前台,这仅在api>23时有效。谁能帮我解决这个问题

你们可以在图像中看到图像的背景。我想通过编程将图像转换成那个形状

甚至我也尝试使用
Gradient Drawable
,但都是徒劳的

代码:


您可以通过应用clipPath来更改imageView类的
onDraw
方法:

@Override
protected void onDraw(Canvas canvas) {
    float[] radii = new float[8];
    radii[0] = radius; // Goes clockwise, so this is the top left corner start position.
    radii[1] = radius; // top left end position.
    radii[2] = radius;
    radii[3] = radius;
    // Skipping 4 and 5 because thats the bottom right corner.
    radii[6] = radius;
    radii[7] = radius;
    Path clipPath = new Path();
    clipPath.addRoundRect(new RectF(0, 0, this.getWidth(), this.getHeight()), radii, Path.Direction.CW);
    canvas.clipPath(clipPath);
    super.onDraw(canvas);
}
参考文献:


如果要创建可绘制图像,则可以为不同的角设置不同的半径,如

<corners
    android:topRightRadius="15dp"
    android:topLeftRadius="15dp"
    android:bottomLeftRadius="15dp"/>
无效设置角半径(浮动[]半径)

指定4个角点中每个角点的半径。对于每个角点,数组 包含2个值,[X_半径,Y_半径]。角落是有序的 左上角,右上角,右下角,左下角。这个物业是 仅当形状为矩形类型时才有效

要设置颜色,请使用
gradientDrawable.setColor(您的颜色)
方法,您可以在那里使用多种颜色进行渐变外观


这里(15,15,15,15,15,15,0,0)建议从左上角开始的所有4个角的X半径和Y半径。

最后我通过参考和解决了我的问题

最后,ImageView类如下所示:

public class RoundedImageView extends ImageView {

private Path mMaskPath;
private Paint mMaskPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
private int mCornerRadius = 10;

public RoundedImageView(Context context) {
    super(context);

    init();
}

public RoundedImageView(Context context, AttributeSet attributeSet) {
    super(context, attributeSet);

    init();
}

public RoundedImageView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);

    init();
}

private void init() {
    ViewCompat.setLayerType(this, ViewCompat.LAYER_TYPE_SOFTWARE, null);
    mMaskPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
}


public void setCornerRadius(int cornerRadius) {
    mCornerRadius = cornerRadius;
    generateMaskPath(getWidth(), getHeight());
    invalidate();
}

@Override
protected void onSizeChanged(int w, int h, int oldW, int oldH) {
    super.onSizeChanged(w, h, oldW, oldH);

    if (w != oldW || h != oldH) {
        generateMaskPath(w, h);
    }
}

private void generateMaskPath(int w, int h) {
    mMaskPath = new Path();
    float[] radii = new float[8];
    radii[0] = 20; // Goes clockwise, so this is the top left corner start position.
    radii[1] = 20; // top left end position.
    radii[2] = 20;
    radii[3] = 20;
    // Skipping 4 and 5 because thats the bottom right corner.
    radii[6] = 20;
    radii[7] = 20;
    mMaskPath.addRoundRect(new RectF(0,0,w,h), radii, Path.Direction.CW);
    mMaskPath.setFillType(Path.FillType.INVERSE_WINDING);
}

@SuppressLint("WrongConstant")
@Override
protected void onDraw(Canvas canvas) {
    if(canvas.isOpaque()) { // If canvas is opaque, make it transparent
        canvas.saveLayerAlpha(0, 0, canvas.getWidth(), canvas.getHeight(), 255, Canvas.HAS_ALPHA_LAYER_SAVE_FLAG);
    }

    super.onDraw(canvas);

    if(mMaskPath != null) {
        canvas.drawPath(mMaskPath, mMaskPaint);
    }
}
 }

先生,非常感谢您的回答,但它显示无法解析此行的构造函数clipPath.addRoundRect(新的RectF(0,0,this.getWidth(),this.getHeight(),radii,Path.Direction.CW);@user8027365我忘记了一个括号来关闭
RectF
,在示例中修复了它。嗯,你将它添加到ImageView扩展类?或者你正在以不同的方式创建ImageView?它不会改变任何东西。你能详细说明如何在我的案例@Kunushould中使用Gradient Drawable吗?我将这个渐变设置为我的背景吗?@kunui如果您使用单色,它将与普通背景相同。这不会改变任何东西。您可以用更新的代码更新您的问题吗?
setBackgroundDrawable
不推荐使用。请改用
setBackground
GradientDrawable gradientDrawable= new GradientDrawable();
gradientDrawable.setCornerRadii(15,15,15,15,15,15,0,0);
public class RoundedImageView extends ImageView {

private Path mMaskPath;
private Paint mMaskPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
private int mCornerRadius = 10;

public RoundedImageView(Context context) {
    super(context);

    init();
}

public RoundedImageView(Context context, AttributeSet attributeSet) {
    super(context, attributeSet);

    init();
}

public RoundedImageView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);

    init();
}

private void init() {
    ViewCompat.setLayerType(this, ViewCompat.LAYER_TYPE_SOFTWARE, null);
    mMaskPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
}


public void setCornerRadius(int cornerRadius) {
    mCornerRadius = cornerRadius;
    generateMaskPath(getWidth(), getHeight());
    invalidate();
}

@Override
protected void onSizeChanged(int w, int h, int oldW, int oldH) {
    super.onSizeChanged(w, h, oldW, oldH);

    if (w != oldW || h != oldH) {
        generateMaskPath(w, h);
    }
}

private void generateMaskPath(int w, int h) {
    mMaskPath = new Path();
    float[] radii = new float[8];
    radii[0] = 20; // Goes clockwise, so this is the top left corner start position.
    radii[1] = 20; // top left end position.
    radii[2] = 20;
    radii[3] = 20;
    // Skipping 4 and 5 because thats the bottom right corner.
    radii[6] = 20;
    radii[7] = 20;
    mMaskPath.addRoundRect(new RectF(0,0,w,h), radii, Path.Direction.CW);
    mMaskPath.setFillType(Path.FillType.INVERSE_WINDING);
}

@SuppressLint("WrongConstant")
@Override
protected void onDraw(Canvas canvas) {
    if(canvas.isOpaque()) { // If canvas is opaque, make it transparent
        canvas.saveLayerAlpha(0, 0, canvas.getWidth(), canvas.getHeight(), 255, Canvas.HAS_ALPHA_LAYER_SAVE_FLAG);
    }

    super.onDraw(canvas);

    if(mMaskPath != null) {
        canvas.drawPath(mMaskPath, mMaskPaint);
    }
}
 }