onCreateDrawableState中的setBackground

时间:2014-07-29 06:52:03

标签: java android android-layout

我有一种情况需要在onCreateDrawableState中动态地根据条件设置自定义按钮的setBackground。 所以我的代码就像这样

public class MyButton extends Button  {
public boolean nightMode = false;
private Drawable dayBackground, nightBackgound;
public MyButton(Context context, AttributeSet attrs) {
    super(context, attrs);
    setDuplicateParentStateEnabled(true);
    TypedArray a = context.getTheme().obtainStyledAttributes(
            attrs,
            R.styleable.QITheme,
            0, 0);

    try {
        dayBackground = a.getDrawable(R.styleable.MyTheme_dayBackground);
        nightBackgound = a.getDrawable(R.styleable.MyTheme_nightBackground);
    } finally {
        a.recycle();
    }

}
@Override
protected int[] onCreateDrawableState(int extraSpace) {
    int[] state = super.onCreateDrawableState(extraSpace+1);
    if (CurrentThemeManager.isNightMode()) {
        if(nightBackgound != null)
            setBackground(nightBackgound);
    } else {
        if(dayBackground != null)
            setBackground(dayBackground);
    }
    return state;
}

}

但是由于setBackground间接调用onCreateDrawableState,因为无限递归调用而得到StackOverflowError

java.lang.StackOverflowError
        at android.view.ViewGroup.onCreateDrawableState(ViewGroup.java:5370)
        at android.view.View.onCreateDrawableState(View.java:14635)
        at android.view.ViewGroup.onCreateDrawableState(ViewGroup.java:5370)
        at my.mytheme.widget.MyButton.onCreateDrawableState(MyButton.java:69)
        at android.view.View.getDrawableState(View.java:14611)
        at android.view.View.setBackgroundDrawable(View.java:14837)
        at android.view.View.setBackground(View.java:14777)
        at my.mytheme.widget.MyButton.onCreateDrawableState(MyButton.java:76)
        at android.view.View.getDrawableState(View.java:14611)
        at android.view.View.setBackgroundDrawable(View.java:14837)
        at android.view.View.setBackground(View.java:14777)
        at my.mytheme.widget.MyButton.onCreateDrawableState(MyButton.java:76)
        at android.view.View.getDrawableState(View.java:14611)
        at android.view.View.setBackgroundDrawable(View.java:14837)
        at android.view.View.setBackground(View.java:14777)
        at my.mytheme.widget.MyButton.onCreateDrawableState(MyButton.java:76)
        at android.view.View.getDrawableState(View.java:14611)
        at android.view.View.setBackgroundDrawable(View.java:14837)
        at android.view.View.setBackground(View.java:14777)
        at my.mytheme.widget.MyButton.onCreateDrawableState(MyButton.java:76)
        at android.view.View.getDrawableState(View.java:14611)
        at android.view.View.setBackgroundDrawable(View.java:14837)
        at android.view.View.setBackground(View.java:14777)
        at my.mytheme.widget.MyButton.onCreateDrawableState(MyButton.java:76)
        at android.view.View.getDrawableState(View.java:14611)
        at android.view.View.setBackgroundDrawable(View.java:14837)
        at android.view.View.setBackground(View.java:14777)
        at my.mytheme.widget.MyButton.onCreateDrawableState(MyButton.java:76)
        at android.view.View.getDrawableState(View.java:14611)
        at android.view.View.setBackgroundDrawable(View.java:14837)
        at android.view.View.setBackground(View.java:14777)
        at my.mytheme.widget.MyButton.onCreateDrawableState(MyButton.java:76)
        at android.view.View.getDrawableState(View.java:14611)
        at android.view.View.setBackgroundDrawable(View.java:14837)
        at android.view.View.setBackground(View.java:14777)
        at my.mytheme.widget.MyButton.onCreateDrawableState(MyButton.java:76)
        at android.view.View.getDrawableState(View.java:14611)
        at android.view.View.setBackgroundDrawable(View.java:14837)
        at android.view.View.setBackground(View.java:14777)
        at my.mytheme.widget.MyButton.onCreateDrawableState(MyButton.java:76)
        at android.view.View.getDrawableState(View.java:14611)
        at android.view.View.setBackgroundDrawable(View.java:14837)
        at android.view.View.setBackground(View.java:14777)
        at my.mytheme.widget.MyButton.onCreateDrawableState(MyButton.java:76)
        at android.view.View.getDrawableState(View.java:14611)
        at android.view.View.setBackgroundDrawable(View.java:14837)
        at android.view.View.setBackground(View.java:14777)
        at my.mytheme.widget.MyButton.onCreateDrawableState(MyButton.java:76

有人可以帮我解决这个StackOverflowError吗?

2 个答案:

答案 0 :(得分:2)

您不应该从setBackground致电onCreateDrawableState。这是一种懒惰的方式。但是应该从drawable改变 state

像这样做饭:

  1. 在选择器中定义您的drawable(例如,使用state_checked)
  2. <item android:state_checked="false"
        android:drawable="@drawable/night_image" />
    <item android:state_checked="true"
        android:drawable="@drawable/day_image" />
    
    1. 在自定义视图中添加状态处理

      class YourFancyView extends SomeView implement Checkable {
      
          private static final int[] CHECKED_STATE_SET = {
                  android.R.attr.state_checked
          };
      
          @Override
              protected int[] onCreateDrawableState(int extraSpace) {
                  final int[] drawableState = super.onCreateDrawableState(extraSpace + 1);
      
                  if (isChecked()) {
                      mergeDrawableStates(drawableState, CHECKED_STATE_SET);
                  }
                  return drawableState;
              }
      
      @Override
      public void setChecked(boolean checked) {
          if(mChecked != checked) {
              mChecked = checked;
              refreshDrawableState();
      
          }
      }
      
    2. 下一步 - 编写任何合理的方式来设置checked状态。

      YourFancyView v = new YourFancyView();
      if(itIsTime)v.setChecked(true);

    3. 这应该可以解决问题。

答案 1 :(得分:0)

我不确定这是否能解决你遇到的问题,但我认为你应该用setBackgroundDrawable()取代setBackground()