2012-06-26 7 views
1

У меня есть класс CustomButton (продолжается LinearLayout), где я раздуваю макет, содержащий ToggleButton (на самом деле это сложнее, но я упростил здесь проблему).ToggleButton изменение состояния при изменении ориентации

public class CustomButton extends LinearLayout { 

    private ToggleButton toggleOnOffButton; 

    public CustomButton(Context context, AttributeSet attrs) { 
     super(context, attrs); 
     LayoutInflater.from(context).inflate(R.layout.custom_button_layout, this); 
    } 

    @Override 
    protected void onFinishInflate() { 
     toggleOnOffButton = (ToggleButton) findViewById(R.id.toggle_on_off_button); 
     super.onFinishInflate(); 
    } 

    public ToggleButton getToggleOnOffButton() { 
     return toggleOnOffButton; 
    } 
} 

custom_button_layout.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
       android:layout_width="fill_parent" 
       android:layout_height="wrap_content"> 

    <ToggleButton android:id="@+id/toggle_on_off_button" 
        android:layout_width="wrap_content" 
        android:layout_height="wrap_content" 
        android:textOff="Off" 
        android:textOn="On" 
        android:layout_alignParentRight="true" 
      /> 
</RelativeLayout> 

У меня есть деятельность, где я раздуть макет с 2 CustomButton -s. Состояние включения/выключения первого toggleButton сохраняется в общих настройках, и я загружаю значение оттуда в onCreate.

public class FirstActivity extends Activity 
{ 
    private CustomButton customButton; 
    private ToggleButton toggleBut; 

    @Override 
    public void onCreate(Bundle savedInstanceState) 
    { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main); 

     customButton = (CustomButton)findViewById(R.id.toggleButton); 
     toggleBut = customButton.getToggleOnOffButton(); 

     boolean saved = loadPreferences("toggleBut"); 
     toggleBut.setChecked(saved); 
     toggleBut.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View view) { 
       boolean checked = toggleBut.isChecked(); 
       savePreferences("toggleBut", checked); 
      } 
     }); 
    } 

    private void savePreferences(String key, boolean value){ 
     SharedPreferences sharedPreferences = getPreferences(MODE_PRIVATE); 
     SharedPreferences.Editor editor = sharedPreferences.edit(); 
     editor.putBoolean(key, value); 
     editor.commit(); 
    } 

    private boolean loadPreferences(String key){ 
     SharedPreferences sharedPreferences = getPreferences(MODE_PRIVATE); 
     return sharedPreferences.getBoolean(key, true); 
    } 
} 

main.xml

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
       android:orientation="vertical" 
       android:layout_width="fill_parent" 
       android:layout_height="fill_parent"> 
    <com.example.example.cs.ssd.custom.CustomButton 
      android:id="@+id/toggleButton" 
      android:layout_width="fill_parent" 
      android:layout_height="wrap_content" 
      /> 

    <com.example.example.cs.ssd.custom.CustomButton 
      android:id="@+id/toggleButton2" 
      android:layout_width="fill_parent" 
      android:layout_height="wrap_content" 
      /> 
</LinearLayout> 

Когда я запуска приложения первый ToggleButton включен. Когда я изменить ориентацию экрана, автоматически первый ToggleButton стать Off, даже saved имеет значение true и называется toggleBut.setChecked(saved);, и я думаю, что это имеет отношение к CutomButton я создал, потому что если main.xml макета содержит только 1 CustomButton этой проблемы не воспроизводится. Я не уверен, что я делаю неправильно ... Вот архив с указанным кодом (как проект): archive

ответ

5

Если вы хотите, чтобы ваш CustomButton сохранить свое текущее состояние после изменения ориентации просто переопределить onSaveInstanceState() и onRestoreInstanceState().

Решение

Я побежал через свой код и заметил, что состояние toggleBut «s был быть изменен после onActivityCreated(), но до OnStart(). Для того, чтобы избежать любого из этих методов переопределять настройки переключаемые, я просто переехал эти строки из onViewCreated():

boolean saved = loadPreferences("toggleBut"); 
toggleBut.setChecked(saved); 

и поместить их в onResume(). Надеюсь, это поможет!

Лучшее решение

Ваша установка ToggleButton будут перезапись, когда система пытается восстановить по умолчанию saveInstanceState, вероятно, в Fragment.onActivityCreated().

В CustomButton, переопределить эти функции следующим образом:

@Override 
protected Parcelable onSaveInstanceState() { 
    Bundle state = new Bundle(); 
    state.putParcelable("default", super.onSaveInstanceState()); 
    state.putParcelable("toggle", toggleOnOffButton.onSaveInstanceState()); 
    return state; 
} 

@Override 
protected void onRestoreInstanceState(Parcelable state) { 
    Bundle bundle = (Bundle) state; 
    super.onRestoreInstanceState(bundle.getParcelable("default")); 
    toggleOnOffButton.onRestoreInstanceState(bundle.getParcelable("toggle")); 
}; 

Поймите, что система будет изменять состояние ToggleButton, без еще одной вещи. Но позвольте мне попытаться объяснить, что, происходит сейчас:

  • onActivityCreated(Bundle savedInstanceState) передает это savedInstanceState каждому элементу макета путем вызова «onRestoreInstanceState (Bundle savedInstanceState)`.
  • onRestoreInstanceState() сначала начинается с корневого элемента макета и пересекает иерархию макета (в этом случае он устанавливает проверенное состояние каждого ToggleButton последним).
  • Поскольку методы по умолчанию явно не работают, нам необходимо определить наш собственный метод сохранения/восстановления для ToggleButtons. В противном случае любые изменения, которые мы сделать, прежде чем система вызывает onRestoreInstanceState() будет изменен снова системой ...

Итак, наконец, мы будем исключать из ToggleButtons такое поведение по умолчанию, добавив следующую строку в CustomButton.onFinishInflate ():

toggleOnOffButton.setSaveEnabled(false); 

Voila, ваши пользовательские кнопки автоматически сохраняют свое состояние.

+0

проблема немного сложнее; Я на самом деле использую фрагменты, и в приложении я не могу изменить ориентацию экрана - вынужден быть портретным. Если я заменил фрагмент, который содержит эти 2 пользовательские кнопки с новым, и я вернулся, также изменилось состояние первого toggleButton, и я не вижу никакой логики, почему это происходит ... – Paul

+0

Чтобы быть ясным: если CustomButtons ' A' & 'B' верны, когда вы возвращаете только CustomButton' A' изменяет состояние на false? – Sam

+0

Нет, оба. Их значение по умолчанию истинно, пользователь переходит к другому действию/фрагменту, а при возврате оба значения false. – Paul

Смежные вопросы