Similar to this question asked over 10 years ago: banded background with two colors?
I need to create a drawable to be the background of a generic view that has two distinct rectangular striped colors, like a flag. Bonus if I can make one of the rectangles have curvy corners. Unfortunately, I need to set the colors dynamically, so I cannot define this drawable in xml. How do I accomplish this in Kotlin.
My best guess was this, but it doesn't work:
background = LayerDrawable(
arrayOf(
GradientDrawable().apply {
shape = GradientDrawable.RECTANGLE
layout(0, 0, 100, 20)
background = styles.rootBackground
},
GradientDrawable().apply {
shape = GradientDrawable.RECTANGLE
cornerRadii = floatArrayOf(8f, 8f, 8f, 8f, 0f, 0f, 0f, 0f)
layout(0, 20, 100, 40)
color = styles.robotTextBackgroundColor //requires color state list ?!
}
)
)
Unfortunately, I need to set the colors dynamically, so I cannot define this drawable in xml.
No, you can do that as an XML drawable, inflate into code, then change the color. That would be much easier than starting from scratch in code.
But this requires to attach ids to the layer list items that you need to change their colors
Here is a demo from the referenced post:
R.drawable.test:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/redRect"
android:bottom="20dp">
<shape android:shape="rectangle">
<size android:height="20dp" />
<solid android:color="#ff0000" />
</shape>
</item>
<item
android:id="@+id/blueRect"
android:top="20dp">
<shape android:shape="rectangle">
<size android:height="20dp" />
<solid android:color="#0000ff" />
</shape>
</item>
</layer-list>
Here we'll change the color of the redRect
item from red to green, then set the entire drawable to the root view background:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val background = ResourcesCompat.getDrawable(resources, R.drawable.test, null)
if (background is LayerDrawable) {
val bgLayer =
background.findDrawableByLayerId(R.id.redRect) as GradientDrawable
bgLayer.setColor(Color.GREEN)
findViewById<ConstraintLayout>(R.id.root).background = background
}
}
Bonus if I can make one of the rectangles have curvy corners.
You'd use the <corners>
tag within the shape, and define the radius:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/redRect"
android:bottom="20dp">
<shape android:shape="rectangle">
<size android:height="20dp" />
<solid android:color="#ff0000" />
<corners android:radius="30dp" />
</shape>
</item>
<item
android:id="@+id/blueRect"
android:top="20dp">
<shape android:shape="rectangle">
<size android:height="20dp" />
<solid android:color="#0000ff" />
<corners
android:bottomLeftRadius="30dp"
android:bottomRightRadius="30dp" />
</shape>
</item>
</layer-list>