我有一个自定义视图,让我们说这是它的代码:
public class CustomView extends View {
boolean visible;
boolean enabled;
public CustomView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.CustomView, 0, 0);
try {
visible = a.getBoolean(R.styleable.CustomView_visible, true);
enabled = a.getBoolean(R.styleable.CustomView_enabled, true);
} finally {
a.recycle();
}
// Apply XML attributes here
}
@Override
public Parcelable onSaveInstanceState() {
// Save instance state
Bundle bundle = new Bundle();
bundle.putParcelable("superState", super.onSaveInstanceState());
bundle.putBoolean("visible", visible);
bundle.putBoolean("enabled", enabled);
return bundle;
}
@Override
public void onRestoreInstanceState(Parcelable state) {
// Restore instance state
// This is called after constructor
if (state instanceof Bundle) {
Bundle bundle = (Bundle) state;
visible = bundle.getBoolean("visible");
enabled = bundle.getBoolean("enabled");
state = bundle.getParcelable("superState");
}
super.onRestoreInstanceState(state);
}
}
非常简单。我的自定义视图从XML读取属性并应用它们。这些属性在配置更改时保存和恢复。
但如果我有两种不同的布局,例如两种不同的方向:
[layout-port/view.xml]
<CustomView
custom:visible="true"
custom:enabled="true"
[layout-land/view.xml]
<CustomView
custom:visible="false"
custom:enabled="false"
我的问题是,在更改设备方向时,视图状态会保存为可见并启用,但现在XML布局表明视图不应该具有。在onRestoreInstanceState之前调用构造函数,并且XML属性将被保存的状态覆盖。我不希望这样,XML优先于保存状态。
我做错了什么?解决这个问题的最佳方法是什么?
答案 0 :(得分:0)
在您的情况下,您必须将当前方向存储在Parcelable
中以及其他属性,并且仅在恢复方向等于当前方向的情况下应用这些已恢复的属性(即,活动已被OS销毁和恢复)。在您的情况下,我会使用android:tag
来定义当前的方向,如下所示:
[layout-port/view.xml]
<CustomView
android:tag="port"
custom:visible="true"
custom:enabled="true"
[layout-land/view.xml]
<CustomView
android:tag="land"
custom:visible="false"
custom:enabled="false"
然后你的自定义视图类就像:
public class ScheduleView extends View {
String orientation;
boolean visible;
boolean enabled;
public ScheduleView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.CustomView, 0, 0);
try {
visible = a.getBoolean(R.styleable.CustomView_visible, true);
enabled = a.getBoolean(R.styleable.CustomView_enabled, true);
} finally {
a.recycle();
}
orientation = (String) getTag();
}
@Override
public Parcelable onSaveInstanceState() {
// Save instance state
Bundle bundle = new Bundle();
bundle.putParcelable("superState", super.onSaveInstanceState());
bundle.putBoolean("visible", visible);
bundle.putBoolean("enabled", enabled);
bundle.putString("orientation", orientation);
return bundle;
}
@Override
public void onRestoreInstanceState(Parcelable state) {
// Restore instance state
// This is called after constructor
if (state instanceof Bundle) {
Bundle bundle = (Bundle) state;
String restoredOrientation = bundle.getString("orientation");
if (restoredOrientation.equals(orientation)) {
visible = bundle.getBoolean("visible");
enabled = bundle.getBoolean("enabled");
}
state = bundle.getParcelable("superState");
}
super.onRestoreInstanceState(state);
}
}
没有正确测试,但它应该工作。希望它会有所帮助。
答案 1 :(得分:0)
基本上,您需要将状态分为纵向和横向,这意味着您还必须保存特定的配置状态。
final boolean isPortrait =
getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT;
bundle.putBoolean("isPortrait", isPortrait);
然后恢复状态时:
final boolean savedOrientation = bundle.getBoolean("isPortrait");
final boolean currentOrientation =
getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT;
if (savedOrientation == currentOrientation) {
// now retrieve saved values
} else {
// do nothing, values are initialized in constructor
}