我遇到一种情况,需要根据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吗?
最佳答案
您不应从setBackground
呼叫onCreateDrawableState
。这是懒惰的方式。但应改为更改可绘制状态。
像这样煮:
在选择器中定义您的可绘制对象(例如,使用state_checked)
<item android:state_checked="false"
android:drawable="@drawable/night_image" />
<item android:state_checked="true"
android:drawable="@drawable/day_image" />
在您的自定义视图中添加状态处理
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();
}
}
下一步-以任何合理的方式设置
checked
状态的代码。YourFancyView v =新的YourFancyView();
if(itIsTime)v.setChecked(true);
这应该可以解决问题。