我创建了一个扩展viewgroup的类。这个mycustomviewgroup类的一个函数充当扩展button的嵌套类mybutton的容器。
我以正常方式从自定义属性集设置mycustomviewgroup的自定义属性。其中一个属性定义了stateListDrawable,可用于MyButton嵌套类实例的背景。我将其存储在类变量mmybuttonbackground中。

public class MyCustomViewGroup extends ViewGroup {
    private Drawable mMyButtonBackground;
    ...

每次在mycustomviewgroup中创建mybutton的新实例时,我都会设置它的背景。
    MyButton myButton = new MyButton(context);
    myButton.setBackground(mMyButtonBackground);

在运行时,stateListDrawable似乎只适用于最近添加的myButton实例。
例如,假设我在mycustomviewgroup中创建了4个mybutton实例。如果我单击MyButton4,它的后台更改将在StateListDrawable中定义。如果我点击MyButton1到3,它们的背景不会改变,但MyButton4的背景会改变。
从逻辑上讲,这表明这是一个易变的问题。所有MyButton实例共享存储在mmyButtonBackground中的同一StateListDrawable。考虑到这一点,我试过:
    MyButton myButton = new MyButton(context);
    Drawable myButtonBackground = mMyButtonBackground.mutate();
    myButton.setBackground(myButtonBackground);

但这并没有解决问题。我也试着把它具体地描述成一个有状态的图表:
    MyButton myButton = new MyButton(context);
    StateListDrawable myButtonBackground = (StateListDrawable)mMyButtonBackground.mutate();
    myButton.setBackground(myButtonBackground);

这也没有解决问题。在我试图解决这个问题的研究中,我读过this article by Romain Guy on Drawable mutations。我本以为既然stateListDrawable是Drawable的一个子类,我应该可以应用同样的方法,但我似乎无法使它工作。我错过了什么?

最佳答案

根据pskink的答案,问题是您使用了相同的Drawable实例。当您将Drawable设置为背景时,View将注册为该Drawable接收事件的侦听器(考虑到Drawable的新状态,还需要重新绘制View)。因此,您的单个实例StateListDrawable将始终具有最后一个设置为background的View作为回调。这就是它在最后一个Button中工作的原因,但当您对另一个Button执行操作时,它也会重绘相同的Buttons,因为Drawable在其回调View中触发无效。
您只需为每个StateListDrawable创建一个新的Button,就可以避免这种情况。在包装容器中,您可以传递一个属性,该属性的String表示要用作背景的StateListDrawable的名称,存储它并在创建新的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);

09-13 12:36