【问题标题】:How to covert imageview into different shape?如何将imageview转换为不同的形状?
【发布时间】:2018-10-11 13:06:24
【问题描述】:

实际上我想将图像转换为图片中提到的形状。我在SO 中尝试了很多类似的问题,但没有一个有帮助。您可能会建议在 imageView 的前景中使用 drawable,但我必须以编程方式设置前景,这仅有效 api>23 。谁能帮我解决这个问题?

您可以在图像中看到图像的背景。我想以编程方式将图像转换为该形状。

即使我尝试使用Gradient Drawable,但它是徒劳的

代码:

GradientDrawable gradientDrawable= new GradientDrawable();
        float[] radii = new float[8];
        radii[0] = 15; // Goes clockwise, so this is the top left corner start position.
        radii[1] = 15; // top left end position.
        radii[2] = 15;
        radii[3] = 15;
        radii[4]=0;
        radii[5]=0;
        radii[6] = 15;
        radii[7] = 15;
        gradientDrawable.setCornerRadii(radii);
        holder.img.setBackgroundDrawable(gradientDrawable);

【问题讨论】:

  • setBackgroundDrawable 已弃用。而是使用setBackground

标签: android imageview android-shapedrawable


【解决方案1】:

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

最后 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);
    }
}
 }

【讨论】:

    【解决方案2】:

    如果你想创建一个可绘制的图像,那么你可以为不同的角落设置不同的半径,比如

    <corners
        android:topRightRadius="15dp"
        android:topLeftRadius="15dp"
        android:bottomLeftRadius="15dp"/>
    

    除此之外,您还可以使用 GradientDrawable 创建背景图像并使用 setCornerRadii 进行可变角半径。

    GradientDrawable 示例

    GradientDrawable gradientDrawable= new GradientDrawable();
    gradientDrawable.setCornerRadii(15,15,15,15,15,15,0,0);
    

    void setCornerRadii (float[] 半径)

    为 4 个角中的每一个指定半径。对于每个角,数组 包含 2 个值,[X_radius, Y_radius]。角落是有序的 左上、右上、右下、左下。该物业是 仅当形状为 RECTANGLE 类型时才有效。

    设置颜色使用gradientDrawable.setColor(YOUR_COLOR)方法,你可以在那里使用多种颜色进行渐变。

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

    【讨论】:

    • 能否请您详细说明如何在我的案例中使用 Gradient Drawable @Kunu
    • 我应该将此渐变设置为我的背景吗? @库努
    • 如果使用单色,则与普通背景相同。
    • 它没有改变任何东西,先生
    • 你能用你更新的代码更新你的问题吗?
    【解决方案3】:

    您可以通过应用 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);
    }
    

    参考:

    【讨论】:

    • 先生非常感谢您的回答,但它显示无法解析此行的构造函数 clipPath.addRoundRect(new RectF(0, 0, this.getWidth(), this.getHeight( ), 半径, Path.Direction.CW);
    • @user8027365 我忘了用括号来封闭RectF,在示例中修复了它。
    • 嗯,你把它添加到你的 ImageView 扩展类中了吗?还是您以不同的方式创建 ImageView?
    • 它没有改变任何东西
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-21
    • 1970-01-01
    • 2011-10-08
    • 1970-01-01
    • 2020-01-07
    • 2019-09-06
    相关资源
    最近更新 更多