6

属性、のは、これがそのコードですとしましょう:はXMLを適用する前に、ビューの状態を復元し、私はカスタムビューを持っている

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によって破壊されて復元された場合)にのみ適用します。

[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" 

そしてカスタムビュークラスは次のように次のようになります:あなたのケースでは、私はこのように現在の向きを定義するためのandroid:tagを使用することになり

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以外の属性を適用したい。アジズベキアンの答えにも同じことが当てはまります。 –

+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 
} 
関連する問題