하는

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 값 복원 후 다시 적용 :

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

그런 상태를 복원 할 때. 또한 복원을 적용하지 않아도되므로 값은 항상 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에없는 속성을 적용하려고합니다. azizbekian의 대답에도 똑같은 것이 적용됩니다. –

+0

죄송하지만 문제가되지 않습니다. 'onRestoreInstanceState' 메소드의'if' 블록 밖에서 실제로 xml 밖의 속성을 적용 할 수 있습니다. – rom4ek

+0

'onRestoreInstanceState'가 항상 이것이 문제라고 말하는 것은 아닙니다. –

0

기본적으로 상태를 세로 및 가로로 구분해야하므로 특정 구성 상태도 저장해야합니다. 다른 변수

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 
}