如何从 Preferences 子屏幕移回到 PreferenceFragmentCompat 中的主屏幕?
How to move back from Preferences subscreen to main screen in 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>
现在,在应用程序中,子屏幕不会打开,直到我在父 activity 中实现 PreferenceFragmentCompat.OnPreferenceStartScreenCallback 接口,如 PreferenceFragmentCompat 文档中所指定。
MainActivity.java
public boolean onPreferenceStartScreen(PreferenceFragmentCompat preferenceFragmentCompat,
PreferenceScreen preferenceScreen) {
preferenceFragmentCompat.setPreferenceScreen(preferenceScreen);
return true;
}
问题就出在这里。在实现界面时,子屏幕打开,但我无法找到返回第一屏幕的方法。
按返回键关闭应用程序。
有什么办法可以在应用栏上放一个后退箭头,这样按下它就会返回主屏幕吗?
通过使用 setPreferenceScreen,您可以将根首选项屏幕设置为子首选项屏幕,这会阻止您使用首选项屏幕的层次结构来返回导航。
我建议您将每个 PreferenceScreen 视为一个 Fragment,并在导航到子屏幕时添加一个新的 Fragment。
@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 项目
我已经添加了一个带有屏幕截图和代码片段的完整工作示例here in this post,希望这对某人有所帮助。
它涵盖以下场景:-- 1) 一个带有两个复选框和一个子屏幕标题的主设置屏幕。 2) 点击子屏幕标题,新的首选项子屏幕打开。 3) 按下后退键,控制进入主设置屏幕。所以背压处理得当
MainActivity 看起来像这样(重写的 onPreferenceStartScreen 方法处理新 window 中新子屏幕的打开):--
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);
}
}
我正在尝试使用 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>
现在,在应用程序中,子屏幕不会打开,直到我在父 activity 中实现 PreferenceFragmentCompat.OnPreferenceStartScreenCallback 接口,如 PreferenceFragmentCompat 文档中所指定。
MainActivity.java
public boolean onPreferenceStartScreen(PreferenceFragmentCompat preferenceFragmentCompat,
PreferenceScreen preferenceScreen) {
preferenceFragmentCompat.setPreferenceScreen(preferenceScreen);
return true;
}
问题就出在这里。在实现界面时,子屏幕打开,但我无法找到返回第一屏幕的方法。
按返回键关闭应用程序。
有什么办法可以在应用栏上放一个后退箭头,这样按下它就会返回主屏幕吗?
通过使用 setPreferenceScreen,您可以将根首选项屏幕设置为子首选项屏幕,这会阻止您使用首选项屏幕的层次结构来返回导航。
我建议您将每个 PreferenceScreen 视为一个 Fragment,并在导航到子屏幕时添加一个新的 Fragment。
@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 项目
我已经添加了一个带有屏幕截图和代码片段的完整工作示例here in this post,希望这对某人有所帮助。
它涵盖以下场景:-- 1) 一个带有两个复选框和一个子屏幕标题的主设置屏幕。 2) 点击子屏幕标题,新的首选项子屏幕打开。 3) 按下后退键,控制进入主设置屏幕。所以背压处理得当
MainActivity 看起来像这样(重写的 onPreferenceStartScreen 方法处理新 window 中新子屏幕的打开):--
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);
}
}