以编程方式设置android形状颜色


168

我正在编辑以使问题更简单,希望能帮助您找到正确的答案。

说我的oval形状如下:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval">
    <solid android:angle="270"
           android:color="#FFFF0000"/>
    <stroke android:width="3dp"
            android:color="#FFAA0055"/>
</shape>

如何从活动类中以编程方式设置颜色?


您将此可绘制对象设置为什么?
维克拉姆

drawable是一个oval并且是ImageView的背景。
Cote Mounyo

如果提出的问题太困难了,是否有办法在画布上绘制多个图像并将分层的最终产品设置为视图的背景?
Cote Mounyo

您可以通过扩展View类并将其用作base允许widgets(RelativeLayoutFrameLayout)重叠的布局中的视图来实现此目的。在此扩展View类中,您可以draw multiple images onto a canvas。但是,在此之前,请先看一下-> 链接(如果还没有的话)。
维克拉姆

Answers:


266

注意:答案已更新,以涵盖background实例为的情况ColorDrawable。感谢Tyler Pfaff指出这一点。

drawable是一个椭圆形,是ImageView的背景

Drawable通过imageView使用获取getBackground()

Drawable background = imageView.getBackground();

检查常规嫌疑犯:

if (background instanceof ShapeDrawable) {
    // cast to 'ShapeDrawable'
    ShapeDrawable shapeDrawable = (ShapeDrawable) background;
    shapeDrawable.getPaint().setColor(ContextCompat.getColor(mContext,R.color.colorToSet));
} else if (background instanceof GradientDrawable) {
    // cast to 'GradientDrawable'
    GradientDrawable gradientDrawable = (GradientDrawable) background;
    gradientDrawable.setColor(ContextCompat.getColor(mContext,R.color.colorToSet));
} else if (background instanceof ColorDrawable) {
    // alpha value may need to be set again after this call
    ColorDrawable colorDrawable = (ColorDrawable) background;
    colorDrawable.setColor(ContextCompat.getColor(mContext,R.color.colorToSet));
}

精简版:

Drawable background = imageView.getBackground();
if (background instanceof ShapeDrawable) {
    ((ShapeDrawable)background).getPaint().setColor(ContextCompat.getColor(mContext,R.color.colorToSet));
} else if (background instanceof GradientDrawable) {
    ((GradientDrawable)background).setColor(ContextCompat.getColor(mContext,R.color.colorToSet));
} else if (background instanceof ColorDrawable) {
    ((ColorDrawable)background).setColor(ContextCompat.getColor(mContext,R.color.colorToSet));
}

请注意,不需要进行空检查。

但是,mutate()如果在其他地方使用了可绘制对象,则应在对其进行修改之前使用它们。(默认情况下,从XML加载的可绘制对象共享相同的状态。)


3
谢谢回答。(+1)。我的代码遇到其他错误,因此很难测试。但这仍然可以设置solid形状的一部分。那stroke部分呢?
Cote Mounyo

1
@TiGer您应该添加@username评论以确保将通知发送给用户。顺便说一句,您将需要子类化ShapeDrawable以设置笔触部分。此处有更多信息:链接。查看评论,因为它提到了已接受答案的问题。
维克拉姆

3
无法将android.graphics.drawable.GradientDrawable强制转换为android.graphics.drawable.ShapeDrawable强制转换对我失败
约翰

3
@John如果您的ImageView's背景设置为GradientDrawablegetBackground()则不会返回ShapeDrawable。相反,使用的GradientDrawable则返回:GradientDrawable gradientDrawable = (GradientDrawable)imageView.getBackground();...... gradientDrawable.setColors(new int[] { color1, color2 });
维克拉姆2014年

2
谢谢..拯救了我的世界。
sid_09,2016年

43

这样做:

    ImageView imgIcon = findViewById(R.id.imgIcon);
    GradientDrawable backgroundGradient = (GradientDrawable)imgIcon.getBackground();
    backgroundGradient.setColor(getResources().getColor(R.color.yellow));

1
@ user3111850 在致电之前,您是否添加android:background了xml甚至setBackground活动中getBackground()?如果您这样做,它应该可以工作。
Lee Yi Hong

41

如今,一种更简单的解决方案是将形状用作背景,然后通过以下方式以编程方式更改其颜色:

view.background.setColorFilter(Color.parseColor("#343434"), PorterDuff.Mode.SRC_ATOP)

有关可用选项,请参见PorterDuff.Mode

更新(API 29):

自API 29起不推荐使用上述方法,并由以下方法代替:

view.background.colorFilter = BlendModeColorFilter(Color.parseColor("#343434"), BlendMode.SRC_ATOP)

有关可用选项,请参见BlendMode


4
正确的一种是: view.getBackground().setColorFilter(Color.parseColor("#343434"), PorterDuff.Mode.SRC_ATOP);由于背景上可能有边框或圆角。
BerkayTurancı19年

1
不错的一个@BerkayTurancı我的形状确实有圆角。我可以省略getBackground()电话。我的imageview.src包含一个形状,并且我使用了:imageIndicator.setColorFilter(toggleColor, PorterDuff.Mode.SRC_ATOP);在哪儿toggleColor是一个以前存储了getColor()结果的int
某人某处

1
拥有PorterDuff.Modefor BlendModeColorFilter不会按要求进行编译BlendMode。因此,对于API 29,应该为view.background.colorFilter = BlendModeColorFilter(Color.parseColor("#343434"), BlendMode.SRC_ATOP)
Onik

好赶上@Onik。我已经相应地更新了答案。谢谢!
Georgios

14

试试这个:

 public void setGradientColors(int bottomColor, int topColor) {
 GradientDrawable gradient = new GradientDrawable(Orientation.BOTTOM_TOP, new int[]  
 {bottomColor, topColor});
 gradient.setShape(GradientDrawable.RECTANGLE);
 gradient.setCornerRadius(10.f);
 this.setBackgroundDrawable(gradient);
 }

为更详细检查此链接

希望对您有所帮助。


对该链接进行投票。但这不是我的问题的答案。
Cote Mounyo

13

希望这可以帮助遇到同样问题的人

GradientDrawable gd = (GradientDrawable) YourImageView.getBackground();
//To shange the solid color
gd.setColor(yourColor)

//To change the stroke color
int width_px = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, youStrokeWidth, getResources().getDisplayMetrics());
gd.setStroke(width_px, yourColor);

1
最初我无法使用它,我发现必须提供yourColor,如下所示:gd.setStroke(width_px, Color.parseColor("#FF5722"));
pwnsauce 2015年

12

如果要给动态视图着色,例如回收者视图项目等,请扩展Vikram的答案。然后,您可能想要在设置颜色之前调用mutate()。如果您不这样做,则具有共同可绘制对象(即背景)的任何视图也将对其可绘制对象进行更改/着色。

public static void setBackgroundColorAndRetainShape(final int color, final Drawable background) {

    if (background instanceof ShapeDrawable) {
        ((ShapeDrawable) background.mutate()).getPaint().setColor(color);
    } else if (background instanceof GradientDrawable) {
        ((GradientDrawable) background.mutate()).setColor(color);
    } else if (background instanceof ColorDrawable) {
        ((ColorDrawable) background.mutate()).setColor(color);
    }else{
        Log.w(TAG,"Not a valid background type");
    }

}

3
需要和额外的检查和参数: if (background instanceof LayerDrawable) { background = ((LayerDrawable) background.mutate()).getDrawable(indexIfLayerDrawable); } if (background instanceof ShapeDrawable)[...]处理使用的背景布局<layer-list ... <item ...
约翰尼

11

不久前回答了这个问题,但是可以通过重写为kotlin扩展功能来使其现代化。

fun Drawable.overrideColor(@ColorInt colorInt: Int) {
    when (this) {
        is GradientDrawable -> setColor(colorInt)
        is ShapeDrawable -> paint.color = colorInt
        is ColorDrawable -> color = colorInt
    }
}

7

这是对我有用的解决方案...也将其写在另一个问题中: 如何动态更改形状颜色?

//get the image button by id
ImageButton myImg = (ImageButton) findViewById(R.id.some_id);

//get drawable from image button
GradientDrawable drawable = (GradientDrawable) myImg.getDrawable();

//set color as integer
//can use Color.parseColor(color) if color is a string
drawable.setColor(color)

4

什么都不适合我,但是当我设置色调颜色时,它可以在Shape Drawable上使用

 Drawable background = imageView.getBackground();
 background.setTint(getRandomColor())

需要android 5.0 API 21


3

我的Kotlin扩展功能版本基于以上带有Compat的答案:

fun Drawable.overrideColor_Ext(context: Context, colorInt: Int) {
    val muted = this.mutate()
    when (muted) {
        is GradientDrawable -> muted.setColor(ContextCompat.getColor(context, colorInt))
        is ShapeDrawable -> muted.paint.setColor(ContextCompat.getColor(context, colorInt))
        is ColorDrawable -> muted.setColor(ContextCompat.getColor(context, colorInt))
        else -> Log.d("Tag", "Not a valid background type")
    }
}

1

半径填充形状的简单方法是:

(view.getBackground()).setColorFilter(Color.parseColor("#FFDE03"), PorterDuff.Mode.SRC_IN);

1

可能我来不及了,但是如果您正在使用Kotlin。有这样的方法

var gd = layoutMain.background as GradientDrawable

 //gd.setCornerRadius(10)
  gd.setColor(ContextCompat.getColor(ctx , R.color.lightblue))
  gd.setStroke(1, ContextCompat.getColor(ctx , R.color.colorPrimary)) // (Strokewidth,colorId)

请享用....


0

对于使用C#Xamarin的任何人,以下是基于Vikram的代码段的方法:

private void SetDrawableColor(Drawable drawable, Android.Graphics.Color color)
{
    switch (drawable)
    {
        case ShapeDrawable sd:
            sd.Paint.Color = color;
            break;
        case GradientDrawable gd:
            gd.SetColor(color);
            break;
        case ColorDrawable cd:
            cd.Color = color;
            break;
    }
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.