如何以编程方式实现圆角和随机背景颜色?

150

我想在运行时使一个视图的角变圆,并根据内容改变视图的颜色。

TextView v = new TextView(context);
v.setText(tagsList.get(i));
if(i%2 == 0){
    v.setBackgroundColor(Color.RED);
}else{
    v.setBackgroundColor(Color.BLUE);
}

v.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT));
v.setPadding(twoDP, twoDP, twoDP, twoDP);               
v.setBackgroundResource(R.drawable.tags_rounded_corners);

我希望设置一个可绘制对象和颜色可以重叠,但实际上并不会。无论最后执行哪个,它都会成为背景。

有没有办法以编程方式创建这个视图,同时记住背景颜色在运行时才能确定?

编辑:目前我只是为了测试在红色和蓝色之间切换。稍后用户将能够选择颜色。

编辑:

tags_rounded_corners.xml:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
    <corners 
         android:bottomRightRadius="2dp" 
         android:bottomLeftRadius="2dp" 
         android:topLeftRadius="2dp" 
         android:topRightRadius="2dp"/>
</shape>

当然,背景颜色和背景图片会互相覆盖。你想要实现什么效果?tags_rounded_corners是什么? - Alex MDC
能否展示更多的代码?看起来很好,所以我想知道你可能使用了listView或重用了现有的textView。 - Chansuk
11个回答

243

不要使用setBackgroundColor方法,应该获取背景图并设置它的颜色:

v.setBackgroundResource(R.drawable.tags_rounded_corners);

GradientDrawable drawable = (GradientDrawable) v.getBackground();
if (i % 2 == 0) {
  drawable.setColor(Color.RED);
} else {
  drawable.setColor(Color.BLUE);
}

另外,您可以在tags_rounded_corners.xml文件中定义填充(padding):

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
  <corners android:radius="4dp" />
  <padding
    android:top="2dp"
    android:left="2dp"
    android:bottom="2dp"
    android:right="2dp" />
</shape> 

完美的答案!使用strock也可以工作,但是我们是否可以使用类似以下的内容来创建它: colorDrawable = resources.getDrawable(R.drawable.x_sd_circle); colorDrawable.setColorFilter(color, PorterDuff.Mode.SRC_ATOP); 如果我们没有边框。 但是在有边框的情况下,您能告诉我PorterDuff.Mode吗,以便描边颜色不会改变? - Akhil Dad
如何通过XML添加背景颜色? - Raj
2
如果“v”是TextView,那么v.getBackground()将会抛出“java.lang.ClassCastException: android.graphics.drawable.StateListDrawable cannot be cast to android.graphics.drawable.GradientDrawable”的异常。这在2013年真的能工作吗? - sonavolob
@sonavolob 你是正确的。它会抛出 ClassCastException 异常。 - Adnan
我有一个只有一个RelativeLayout的XML布局。首先将其膨胀,然后设置setBackgroundResource,接着获取getBackground。在这一行代码中:java.lang.ClassCastException: android.graphics.drawable.LayerDrawable cannot be cast to android.graphics.drawable.GradientDrawable - Dr.jacky
显示剩余6条评论

145

这是一种全面的编程方法,用于设置View的圆角,并添加随机背景颜色。 我尚未测试此代码,但你可以理解其思想。

 GradientDrawable shape =  new GradientDrawable();
 shape.setCornerRadius( 8 );

 // add some color
 // You can add your random color generator here
 // and set color
 if (i % 2 == 0) {
  shape.setColor(Color.RED);
 } else {
  shape.setColor(Color.BLUE);
 }

 // now find your view and add background to it
 View view = (LinearLayout) findViewById( R.id.my_view );
 view.setBackground(shape);

在这里,我们使用渐变可绘制对象,这样我们就可以利用GradientDrawable # setCornerRadius,因为ShapeDrawable没有提供这样的方法。


13
shape.setCornerRadii(corners); 非常有用。 (翻译说明:按要求进行翻译,尽可能保持原文意思和结构的完整性,并使用通俗易懂的中文表达。) - umesh
16
考虑使用PaintDrawable代替GradientDrawable。 它支持圆角和单一颜色,这似乎比渐变更合适。 - Cimlman
2
这个很有效!我在Xamarin中使用它。 var pd = new PaintDrawable(BackgroundColor); pd.SetCornerRadius(15); myView.Background = pd; - Pierre
不错的快速解决方案,但请注意它需要API最低级别为16。 - The Unknown Dev
1
@Anonymous-E,我建议你查找GradientDrawable.setCornerRadii()函数。 - Adam Pisula
显示剩余2条评论

12

我认为最快的做法是:

GradientDrawable gradientDrawable = new GradientDrawable(
            GradientDrawable.Orientation.TOP_BOTTOM, //set a gradient direction 
            new int[] {0xFF757775,0xFF151515}); //set the color of gradient
gradientDrawable.setCornerRadius(10f); //set corner radius

//Apply background to your view
View view = (RelativeLayout) findViewById( R.id.my_view );
if(Build.VERSION.SDK_INT>=16)
     view.setBackground(gradientDrawable);
else view.setBackgroundDrawable(gradientDrawable);    

10
你可以使用DrawableCompat来更好地实现它:
Drawable backgroundDrawable = view.getBackground();             
DrawableCompat.setTint(backgroundDrawable, newColor);

8
由于问题已经得到答复,但我有一点小修改。
GradientDrawable drawable = (GradientDrawable) ContextCompat.getDrawable(context, R.drawable.YOUR_DRAWABLE).mutate();

你可以使用以下代码改变圆角半径:

drawable.setCornerRadius(YOUR_VALUE);

使用以下方法更改颜色:

drawable.setColor(Color.YOUR_COLOR);

可变的可绘制对象保证不会与其他可绘制对象共享其状态。因此,如果您在不使用mutate()的情况下更改半径,则很可能会改变其他对象的状态。它最适合用于特定视图。

最后别忘了设置可绘制对象。

this.setBackground(drawable);

5
如果您没有中风,您可以使用。
colorDrawable = resources.getDrawable(R.drawable.x_sd_circle); 

colorDrawable.setColorFilter(color, PorterDuff.Mode.SRC_ATOP);

但这也会改变笔画颜色


51
我本打算使用这个,但我现在中风了。 - Tim Malseed

4
您可以动态更改任何项(布局,TextView)的颜色。尝试以下代码以编程方式设置颜色:
在 activity.java 文件中:

String quote_bg_color = "#FFC107"
quoteContainer= (LinearLayout)view.findViewById(R.id.id_quotecontainer);
quoteContainer.setBackgroundResource(R.drawable.layout_round);
GradientDrawable drawable = (GradientDrawable) quoteContainer.getBackground();
drawable.setColor(Color.parseColor(quote_bg_color));

在drawable文件夹中创建layout_round.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <solid android:color="@color/colorPrimaryLight"/>
    <stroke android:width="0dp" android:color="#B1BCBE" />
    <corners android:radius="10dp"/>
    <padding android:left="0dp" android:top="0dp" android:right="0dp" android:bottom="0dp" />
</shape>

在activity.xml文件中进行布局

<LinearLayout
        android:id="@+id/id_quotecontainer"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

----other components---

</LinearLayout>



4

将 @cimlman 的 评论 复制到一个顶级答案中以提高其可见性:

PaintDrawable(Color.CYAN).apply {
  setCornerRadius(24f)
}

提示: ShapeDrawable(以及其子类型PaintDrawable)使用默认的内在宽度和高度0。如果该可绘制对象未显示出来,您可能需要手动设置其尺寸:

PaintDrawable(Color.CYAN).apply {
  intrinsicWidth = -1
  intrinsicHeight = -1
  setCornerRadius(24f)
}

-1 是一个神奇的常量,表示 Drawable 没有自己固有的宽度和高度 (来源)。


3

以下是一个使用扩展名的示例。 这假设视图具有相同的宽度和高度。

需要使用布局更改监听器来获取视图大小。 然后,您只需对视图调用此操作,例如myView.setRoundedBackground(Color.WHITE)

fun View.setRoundedBackground(@ColorInt color: Int) {
    addOnLayoutChangeListener(object: View.OnLayoutChangeListener {
        override fun onLayoutChange(v: View?, left: Int, top: Int, right: Int, bottom: Int, oldLeft: Int, oldTop: Int, oldRight: Int, oldBottom: Int) {

            val shape = GradientDrawable()
            shape.cornerRadius = measuredHeight / 2f
            shape.setColor(color)

            background = shape

            removeOnLayoutChangeListener(this)
        }
    })
}

1
public static void setBackground(View v, int backgroundColor, int borderColor) {
        GradientDrawable shape = new GradientDrawable();
        shape.setShape(GradientDrawable.RECTANGLE);
        shape.setCornerRadii(new float[] { 16, 16, 16, 16, 0, 0, 0, 0 });
        shape.setColor(backgroundColor);
        shape.setStroke(3, borderColor);
        v.setBackground(shape);
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接