6

ich eine benutzerdefinierte Ansicht haben, lassen Sie uns sagen, dass dies seinen Code ist:XML Zustand der Ansicht Wiederherstellung vor der Anwendung Attribute

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

ziemlich einfach. Meine benutzerdefinierte Ansicht liest Attribute aus XML und wendet sie an. Diese Attribute werden bei Konfigurationsänderungen gespeichert und wiederhergestellt.

Aber wenn ich zwei verschiedene Layouts, zum Beispiel für zwei unterschiedliche Ausrichtungen:

[layout-port/view.xml] 
<CustomView 
    custom:visible="true" 
    custom:enabled="true" 

[layout-land/view.xml] 
<CustomView 
    custom:visible="false" 
    custom:enabled="false" 

Mein Problem ist, dass, wenn die Geräteausrichtung zu ändern, Ansichtszustand als sichtbar gespeichert und aktiviert ist, aber jetzt XML-Layout-Staaten die Ansicht sollte auch nicht haben. Der Konstruktor wird vor onRestoreInstanceState aufgerufen und die XML-Attribute werden vom gespeicherten Status überschrieben. Ich will das nicht, XML hat Vorrang vor dem gespeicherten Zustand.

Ich mache etwas falsch? Was wäre der beste Weg, dies zu lösen?

+0

speichern die XML-Werte in anderen Variablen und erneut anwenden, sie nach der Restaurierung. Sie können auch keine Wiederherstellung anwenden, also sind die Werte immer die in xml definierten – nandsito

+0

@nandsito Dies ist wahrscheinlich, was ich am Ende tun. Ich dachte nur, dass es vielleicht einen direkteren Weg gibt, dies zu tun, eine Möglichkeit, den Zustand nach dem Parsen von XML wiederherzustellen. Was ich dachte, könnte ich tun, um das AttributeSet in eine Variable zu speichern und am Ende von onRestoreInstanteState XML zu analysieren. Aber onRestoreInstanteState wird nicht aufgerufen, wenn die Ansicht zuerst erstellt wird. –

+0

Android analysiert das XML und wendet seine Attribute im Ansichtskonstruktor an, sodass das XML immer vor dem Wiederherstellungsstatus verarbeitet wird. Wenn Sie diese Reihenfolge ändern möchten, müssen Sie die Variablenwerte – nandsito

Antwort

0

In diesem Fall müssen Sie die aktuelle Ausrichtung zusammen mit anderen Attributen in Parcelable speichern und diese wiederhergestellten Attribute nur dann anwenden, wenn die wiederhergestellte Ausrichtung der aktuellen Ausrichtung entspricht (d. H. Die Aktivität wurde vom Betriebssystem zerstört und wiederhergestellt). In Ihrem Fall würde ich android:tag zur Definition aktuelle Ausrichtung wie folgt verwenden:

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

Und dann würde Ihre benutzerdefinierte Ansicht Klasse wie:

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

Haben es nicht richtig getestet, aber es sollte funktionieren. Ich hoffe, es wird hilfreich sein.

+0

Ich möchte einige gespeicherte Attribute anwenden, die nicht in XML sind. Gleiches gilt für die Antwort von Azizbekian. –

+0

Sorry, aber ich bekomme kein Problem. Sie könnten diese out-of-xml-Attribute auch außerhalb des 'if'-Blocks in der' onRestoreInstanceState'-Methode anwenden. – rom4ek

+0

'OnRestoreInstanceState' wird nicht immer aufgerufen Dies ist das Problem. –

0

Im Grunde müssen Sie die Zustände in Hoch- und Querformat trennen, dh Sie müssen auch den jeweiligen Konfigurationszustand speichern.

final boolean isPortrait = 
      getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT; 
bundle.putBoolean("isPortrait", isPortrait); 

Dann, wenn die Wiederherstellung des Status:

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 
} 
Verwandte Themen