Как вернуться с подэкрана "Установки" на главный экран в PreferenceFragmentCompat?

Я пытаюсь реализовать экран настроек с помощью PreferenceFragmentCompat. У моего предпочтения xml есть подэкран предпочтений, подобный этому:

preferences.xml

    <CheckBoxPreference
        android:defaultValue="false"
        android:key="@string/pref_sound_key"
        android:summary="@string/pref_sound_summary"
        android:title="@string/pref_sound_title" />

    <PreferenceScreen android:title="Inner Screen">
        <CheckBoxPreference
            android:defaultValue="true"
            android:key="@string/key_1"
            android:title="@string/title_1" />

        <CheckBoxPreference
            android:defaultValue="true"
            android:key="@string/key_1"
            android:title="@string/title_1" />

        <CheckBoxPreference
            android:defaultValue="true"
            android:key="@string/key_2"
            android:title="@string/title_2" />

        <CheckBoxPreference
            android:defaultValue="true"
            android:key="@string/key_3"
            android:title="@string/title_3" />
    </PreferenceScreen>

</PreferenceScreen>

Главный экран настроек

Теперь в приложении подэкран не открывается, пока я не реализую интерфейс PreferenceFragmentCompat.OnPreferenceStartScreenCallback в родительском действии, как указано в документе PreferenceFragmentCompat.

MainActivity.java

public boolean onPreferenceStartScreen(PreferenceFragmentCompat preferenceFragmentCompat,
 PreferenceScreen preferenceScreen) {    
    preferenceFragmentCompat.setPreferenceScreen(preferenceScreen);
    return true;
}

Вот где возникает проблема. При реализации интерфейса открывается подэкран, но тогда я не могу найти способ вернуться к первому экрану.

Подэкран настроек

Нажатие клавиши назад закрывает приложение.

Есть ли способ, которым я могу поставить стрелку назад на панели приложений, чтобы при нажатии на нее вернулся главный экран?

2 ответа

Решение

Используя setPreferenceScreen, вы устанавливаете экран корневых предпочтений на экран вспомогательных предпочтений, который не позволяет вам иметь иерархию экранов предпочтений для перехода назад.

Я предлагаю вам рассматривать каждый PreferenceScreen как фрагмент и добавлять новый фрагмент при переходе на дополнительный экран.

@Override
public boolean onPreferenceStartScreen(PreferenceFragmentCompat preferenceFragmentCompat,
                                       PreferenceScreen preferenceScreen) {
    FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
    MyPreferenceFragment fragment = new MyPreferenceFragment();
    Bundle args = new Bundle();
    args.putString(PreferenceFragmentCompat.ARG_PREFERENCE_ROOT, preferenceScreen.getKey());
    fragment.setArguments(args);
    ft.add(R.id.fragment_container, fragment, preferenceScreen.getKey());
    ft.addToBackStack(preferenceScreen.getKey());
    ft.commit();
    return true;
}

MyPreferenceFragment

public class MyPreferenceFragment extends AppPreferenceFragment {

   public static final String FRAGMENT_TAG = "my_preference_fragment";

   public MyPreferenceFragment() {
   }

   @Override
   public void onCreatePreferences(Bundle bundle, String rootKey) {
       setPreferencesFromResource(R.xml.preferences, rootKey);
   }
}

AppPreferenceFragment

public abstract class AppPreferenceFragment extends PreferenceFragmentCompat {

@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);

    // Set the default white background in the view so as to avoid transparency
      view.setBackgroundColor(
              ContextCompat.getColor(getContext(), R.color.background_material_light));

  }
}

Таким образом, когда вы нажимаете кнопку "Назад", каждый фрагмент извлекается из стека.

Для получения дополнительной информации см. Этот проект GitHub

Я добавил полный рабочий пример со скриншотами и фрагментами кода здесь в этом посте, я надеюсь, что это будет кому-то полезно.

Он охватывает следующие сценарии: - 1) Главный экран настроек с двумя флажками и заголовком подэкрана. 2) При щелчке заголовка подэкрана открывается новый подэкран настроек. 3) При нажатии на кнопку управления происходит переход к основному экрану настроек. Таким образом, задний пресс обрабатывается правильно.

MainActivity выглядит следующим образом (переопределенный метод onPreferenceStartScreen обрабатывает открытие нового подэкрана в новом окне):

  public class MainActivity extends AppCompatActivity implements PreferenceFragmentCompat.OnPreferenceStartScreenCallback {

    private static final String TAG = MainActivity.class.getName();

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        FragmentManager fragmentManager = getSupportFragmentManager();
        Fragment fragment = null;
        if (savedInstanceState == null) {
            FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
            fragment = new AdvancedSettingsFragment().newInstance("Advanced Setting");
            fragmentTransaction.add(R.id.fragment_container, fragment);
            fragmentTransaction.commit();
        }
    }

    @Override
        public boolean onPreferenceStartScreen(PreferenceFragmentCompat preferenceFragmentCompat,
                                           PreferenceScreen preferenceScreen) {
        Log.d(TAG, "callback called to attach the preference sub screen");
        FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
        AdvancedSettingsSubScreenFragment fragment = AdvancedSettingsSubScreenFragment.newInstance("Advanced Settings Subscreen");
        Bundle args = new Bundle();
        //Defining the sub screen as new root for the  subscreen
        args.putString(PreferenceFragmentCompat.ARG_PREFERENCE_ROOT, preferenceScreen.getKey());
        fragment.setArguments(args);
        ft.replace(R.id.fragment_container, fragment, preferenceScreen.getKey());
        ft.addToBackStack(null);
        ft.commit();
        return true;
    }

и, наконец, в подэкране фрагмент setPreferencesFromResource(R.xml.preferences, rootKey); обрабатывает прикрепление подэкрана к корневому ключу.

public class AdvancedSettingsSubScreenFragment extends PreferenceFragmentCompat {
    private static final String TAG = AdvancedSettingsSubScreenFragment.class.getName();
    public static final String PAGE_ID = "page_id";

    public static AdvancedSettingsSubScreenFragment newInstance(String pageId) {
        AdvancedSettingsSubScreenFragment f = new AdvancedSettingsSubScreenFragment();
        Bundle args = new Bundle();
        args.putString(PAGE_ID, pageId);
        f.setArguments(args);
        return (f);
    }

    @Override
    public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
        // rootKey is the name of preference sub screen key name , here--customPrefKey
        setPreferencesFromResource(R.xml.preferences, rootKey);
        Log.d(TAG, "onCreatePreferences of the sub screen " + rootKey);
    }
}
Другие вопросы по тегам