从公共资源为自定义ViewGroup的多个组件创建StateListDrawable

时间:2013-09-23 07:40:09

标签: android statelistdrawable

我创建了一个扩展ViewGroup的类。此MyCustomViewGroup类的一个函数是作为嵌套类MyButton的容器,它扩展了Button。

我以正常方式从自定义AttributeSet设置MyCustomViewGroup的自定义属性。其中一个属性定义StateListDrawable以用于MyButton嵌套类的实例的背景。我将它存储在Class变量mMyButtonBackground中。

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

每次在MyCustomViewGroup中创建MyButton的新实例时,我都会设置它的背景。

    MyButton myButton = new MyButton(context);
    myButton.setBackground(mMyButtonBackground);

在运行时,StateListDrawable似乎只适用于最近添加的MyButton实例。

例如,假设我在MyCustomViewGroup中创建了4个MyButton实例。如果我单击MyButton number 4,它的背景会发生变化,如StateListDrawable中所定义。如果我点击MyButton 1到3,他们的背景不会改变,但MyButton编号为4。

从逻辑上讲,这表明这是一个可变性问题。所有MyButton实例共享存储在mMyButtonBackground中的相同StateListDrawable。考虑到这一点,我试过了:

    MyButton myButton = new MyButton(context);
    Drawable myButtonBackground = mMyButtonBackground.mutate();
    myButton.setBackground(myButtonBackground);

但这并没有解决问题。我也尝试将其专门用作StateListDrawable:

    MyButton myButton = new MyButton(context);
    StateListDrawable myButtonBackground = (StateListDrawable)mMyButtonBackground.mutate();
    myButton.setBackground(myButtonBackground);

这也没有解决问题。在我试图解决这个问题的研究中,我已阅读this article by Romain Guy on Drawable mutations。我原以为,由于StateListDrawable是Drawable的子类,我应该可以应用相同的方法,但我似乎无法让它工作。我错过了什么?

3 个答案:

答案 0 :(得分:8)

你不能与多个视图共享一个SLD实例,每个视图需要一个SLD,抱歉

答案 1 :(得分:3)

在pskink回答之后,问题是您使用相同的Drawable实例。当您将Drawable设置为背景时,View会将自己注册为Drawable接收事件的监听器(以考虑Drawable的新统计信息,还需要重绘View)。因此,您的单个实例StateListDrawable将始终将最后View作为回调设置为背景。这就是为什么它适用于最后一个Button,但当你对另一个Button采取行动时,它也会重新绘制相同的Buttons,因为Drawable会在其回调中触发无效View {{} 1}}。

您可以通过为每个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);

答案 2 :(得分:1)

根据Resources类的作用(Resources.java),我发现下面的代码可以解决您的问题。

Drawable selector = res.getDrawable(R.drawable.setting_btn_pressed_selector);
view1.setBackgroundDrawable(selector.getConstantState().newDrawable());
view2.setBackgroundDrawable(selector.getConstantState().newDrawable());
view3.setBackgroundDrawable(selector.getConstantState().newDrawable());

但我不知道此代码的副作用。谁知道?随意发表评论或指出我的错误。