I have created a class which extends ViewGroup. One of the functions of this MyCustomViewGroup class is acting as a container for a nested class MyButton which extends Button.
I setup the custom properties for MyCustomViewGroup from a custom AttributeSet in the normal manner. One of the attributes defines the StateListDrawable to use for the background of instances of the MyButton nested class. I store this in a Class variable mMyButtonBackground.
public class MyCustomViewGroup extends ViewGroup {
private Drawable mMyButtonBackground;
...
Each time I create a new instance of MyButton in MyCustomViewGroup I set it's background.
MyButton myButton = new MyButton(context);
myButton.setBackground(mMyButtonBackground);
At run time, the StateListDrawable only seems to be working for the most recently added instance of MyButton.
For example say I create 4 instances of MyButton in MyCustomViewGroup. If I click on MyButton number 4, it's background changes as defined in the StateListDrawable. If I click on MyButton 1 to 3, their backgrounds do not change but MyButton number 4's does.
Logically this would suggest it is a mutability problem. All the MyButton instances are sharing the same StateListDrawable stored in mMyButtonBackground. Considering this, I've tried:
MyButton myButton = new MyButton(context);
Drawable myButtonBackground = mMyButtonBackground.mutate();
myButton.setBackground(myButtonBackground);
This did not solve the issue though. I've also tried specifically casting it as a StateListDrawable:
MyButton myButton = new MyButton(context);
StateListDrawable myButtonBackground = (StateListDrawable)mMyButtonBackground.mutate();
myButton.setBackground(myButtonBackground);
This also did not solve the problem. In my research trying to solve this problem I have have read this article by Romain Guy on Drawable mutations. I would have thought that since a StateListDrawable is a subclass of Drawable, I should be able to apply the same approach, but I can't seem to get it working. What am I missing?
you cannot share one instance of SLD with multiple Views, you need one SLD per View, sorry
Following pskink answer, the problem is that you use the same Drawable
instance. When you set the Drawable
as the background, the View
will register itself as a listener for that Drawable
to receive events(to take in consideration the new stat of a Drawable
, also requiring a redraw of the View
). So, your single instance StateListDrawable
will always have as a callback the last View
for which is set as background. That's why it works for the last Button
, but it also redraws the same Button
when you act upon the other Buttons
as the Drawable
triggers a invalidate on its callback View
.
You could simply avoid this by creating a new StateListDrawable
for each Button
. In the wrapper container you could just pass an attribute with a String
representing the name of the StateListDrawable
to use as the background, store it and use it when creating new Buttons
:
String mBtnDrawable = ""; //initialize in the constructor
// creating new Buttons
MyButton myButton = new MyButton(context);
int drawableId = getContext().getResources().getIdentifier(mBtnDrawable, "drawable", getContext().getPackageName());
StateListDrawable bck = (StateListDrawable) getContext().getResources().getDrawable(drawableId); // maybe also mutate it?
myButton.setBackground(bck);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With