6

我有一个自定义视图,让我们说,这是它的代码:恢复的视图状态属性

public class CustomView extends View { 

    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(); 
     } 

     // 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

存储XML值在其他变量和恢复后重新应用它们。您也可以不适用的恢复,因此它们的值总是被那些XML – nandsito

+0

定义@nandsito这可能是我最后做。我只是想,也许有一个更直接的方法来做到这一点,一种解析XML后恢复状态的方法。我想我可以做的是将AttributeSet保存到一个变量,然后在onRestoreInstanteState结尾解析XML。但是当视图首次创建时,不会调用onRestoreInstanteState。 –

+0

android解析xml并在视图构造函数中应用其属性,因此xml总是在还原状态之前处理。如果您想更改此顺序,则必须手动设置变量值 – nandsito

回答

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); 
    } 
} 

还没有很好的测试,但它应该工作。希望它会有所帮助。

+0

我想申请一些保存的属性,那些不是XML的。 azizbekian的答案也一样。 –

+0

对不起,但我不明白你的问题。你实际上可以在'onRestoreInstanceState'方法的'if'块之外应用那些out-of-xml属性。 – rom4ek

+0

'onRestoreInstanceState'并不总是被调用,这是问题所在。 –

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 
}