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 
}