How to programmatically round corners and set random background colors
Asked Answered
C

11

150

I'd like to round the corners of a view and also change the color of the view based on the contents at runtime.

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);

I was hoping setting a drawable and color would overlap, but they do not. Whichever one I execute second is the resulting background.

Is there any way to programmatically create this view, keeping in mind that the background color won't be decided until runtime?

edit: I'm only swapping between red and blue now for testing. Later the color will be choosable by the user.

edit:

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>
Creationism answered 22/8, 2013 at 22:29 Comment(2)
Of course the background color and background image override each other. What are you trying to achieve? What is tags_rounded_corners?Ebenezer
Could you show more codes? It looks fine, so I wonder you may use kind of listView, or reusing existing textview.Ridden
G
243

Instead of setBackgroundColor, retrieve the background drawable and set its color:

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

Also, you can define the padding within your tags_rounded_corners.xml:

<?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> 
Gerdes answered 23/8, 2013 at 4:58 Comment(7)
Perect answe! it worked with strock as well, but can we make this using something like colorDrawable = resources.getDrawable(R.drawable.x_sd_circle); colorDrawable.setColorFilter(color, PorterDuff.Mode.SRC_ATOP); if we are not having an border. But in case of border can you let me know the PorterDuff.Mode so that stroke color won't changeDecorous
How to add background color as well via XML?Condescend
If "v" is the TextView than v.getBackground() will cast "java.lang.ClassCastException: android.graphics.drawable.StateListDrawable cannot be cast to android.graphics.drawable.GradientDrawable" Was this realy working back in '13?Effervesce
@Effervesce you're right. it gives ClassCastExceptionChilcote
1+ for getbackground() trick. cuz you cant make one corner rounded with GradientDrawable but using getBackground you can ;)Celloidin
I have a XML layout which have just one RelativeLayout. First inflated it. Then setBackgroundResource. Then getBackground. And in this line: java.lang.ClassCastException: android.graphics.drawable.LayerDrawable cannot be cast to android.graphics.drawable.GradientDrawableNard
Gradient Drawable is working with TextView and RelativeLayout, use the same XML shape drawable, don't forget to set property of textview in the xml android:background="@drawable/tags_rounded_corners"Upali
D
146

Total programmatic approach to set rounded corners and add random background color to a View. I have not tested the code, but you get the idea.

 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);

Here we are using gradient drawable so that we can make use of GradientDrawable#setCornerRadius because ShapeDrawable DOES NOT provide any such method.

Dishwasher answered 3/10, 2013 at 6:11 Comment(7)
shape.setCornerRadii(corners); its very usefulPademelon
Consider using PaintDrawable instead of GradientDrawable. It supports rounded corners and just a single color which seems to be more appropriate than a gradient.Bott
This works well! I use it in Xamarin. var pd = new PaintDrawable(BackgroundColor); pd.SetCornerRadius(15); myView.Background = pd;Freemasonry
Nice quick solution, but note that it requires API Minimum Level 16Busty
how to set the corner radius just for one side?Rancourt
@Rancourt I advise you looking up GradientDrawable.setCornerRadii() function.Ahner
Setting rounded corners was the only bit of code in my game that was not programmatic until seeing this solution.Chas
B
12

I think the fastest way to do this is:

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);    
Benedict answered 23/4, 2016 at 7:48 Comment(0)
H
10

You can better achieve it by using the DrawableCompat like this:

Drawable backgroundDrawable = view.getBackground();             
DrawableCompat.setTint(backgroundDrawable, newColor);
Hooge answered 21/2, 2018 at 12:21 Comment(0)
Y
8

As the question has already been answered. But I have a little tweak

GradientDrawable drawable = (GradientDrawable) ContextCompat.getDrawable(context, R.drawable.YOUR_DRAWABLE).mutate();

you can change corner radius with:

drawable.setCornerRadius(YOUR_VALUE);

Change color with:

drawable.setColor(Color.YOUR_COLOR);

A mutable drawable is guaranteed to not share its state with any other drawable. So if you change radius without using mutate(), you are likely to change others state too. It is best suitable for specific views.

At last don't forget to set the drawable.

this.setBackground(drawable);
Yeti answered 23/1, 2021 at 6:45 Comment(0)
D
5

If you are not having a stroke you can use

colorDrawable = resources.getDrawable(R.drawable.x_sd_circle); 

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

but this will also change stroke color

Decorous answered 19/11, 2014 at 12:7 Comment(1)
I was going to use this, but I'm having a stroke.Jacks
G
4

You can dynamically change color of any items ( layout, textview ) . Try below code to set color programmatically in layout

in activity.java file


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));

create layout_round.xml in drawable folder

<?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>

layout in activity.xml file

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

----other components---

</LinearLayout>


Galvanic answered 31/8, 2019 at 8:18 Comment(0)
D
4

Copying @cimlman's comment into a top-level answer for more visibility:

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

FYI: ShapeDrawable (and its subtype, PaintDrawable) uses default intrinsic width and height of 0. If the drawable does not show up in your usecase, you might have to set the dimensions manually:

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

-1 is a magic constant which indicates that a Drawable has no intrinsic width and height of its own (Source).

Deaton answered 23/10, 2019 at 21:56 Comment(0)
S
3

Here's an example using an extension. This assumes the view has the same width and height.

Need to use a layout change listener to get the view size. Then you can just call this on a view like this 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)
        }
    })
}
Schroer answered 2/9, 2019 at 23:41 Comment(0)
A
2
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);
    }
Aldos answered 12/6, 2022 at 19:12 Comment(0)
J
-1

Add the code inside the doOnLayout {} it will work

Jadotville answered 5/5, 2023 at 12:51 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.