我在support-v7库的PreferenceFragment
中使用ActionBarActivity
在我有Toolbar
的活动中。一切顺利,直到我打开一个嵌套的PreferenceScreen
在打开的屏幕中隐藏了Toolbar
。
也许有人知道这个问题的解决方法?
偏好设置xml-file:
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
<PreferenceCategory android:title="Main category" >
<EditTextPreference
android:defaultValue="defaultValue"
android:key="key_global_setting"
android:title="Global title" />
</PreferenceCategory>
<PreferenceCategory android:title="Nested screens" >
<PreferenceScreen
android:persistent="false"
android:title="@string/settings_facility_title" >
<CheckBoxPreference
android:defaultValue="false"
android:key="nested_screen_1_1"
android:title="Nested screen 1.1 check box" />
<CheckBoxPreference
android:defaultValue="true"
android:key="nested_screen_1_2"
android:title="Nested screen 1.2 check box" />
</PreferenceScreen>
<PreferenceScreen
android:persistent="false"
android:title="@string/settings_menu_screen_title" >
<CheckBoxPreference
android:defaultValue="true"
android:key="nested_screen2"
android:title="Nested screen 2 check box" />
</PreferenceScreen>
</PreferenceCategory>
</PreferenceScreen>
活动布局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".SettingsScreen" >
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
style="@style/Toolbar" />
<FrameLayout
android:id="@+id/contentSettings"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
答案 0 :(得分:27)
我自己找到了解决方案。我使用了所有这个嵌套PreferenceScreen's
的小方法。我只是对不同的xml-preference
文件进行了分离,创建了一个扩展Fragment
的附加PreferenceFragment
,并在那里显示了一个合适的嵌套首选项屏幕。
也许有人会觉得这很有用。
以下一些代码示例:
<强> main_preferences.xml 强>
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
<PreferenceCategory android:title="Main category" >
<EditTextPreference
android:defaultValue="defaultValue"
android:key="key_global_setting"
android:title="Global title" />
</PreferenceCategory>
<PreferenceCategory android:title="Nested screens" >
<Preference
android:key="NESTED_KEY1"
android:persistent="false"
android:title="Nested screen #1" />
<Preference
android:key="NESTED_KEY2"
android:persistent="false"
android:title="Nested screen #2" />
</PreferenceCategory>
</PreferenceScreen>
<强> nested_screen1_preferences.xml 强>
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
android:title="Nested screen #1" >
<CheckBoxPreference
android:defaultValue="false"
android:key="nested_screen_1_1"
android:title="Nested screen 1.1 check box" />
<CheckBoxPreference
android:defaultValue="true"
android:key="nested_screen_1_2"
android:title="Nested screen 1.2 check box" />
</PreferenceScreen>
<强> nested_screen2_preferences.xml 强>
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
android:title="Nested screen #2">
<CheckBoxPreference
android:defaultValue="true"
android:key="nested_screen2"
android:title="Nested screen 2 check box" />
</PreferenceScreen>
<强> SettingsActivity.java 强>
public class SettingsActivity extends ActionBarActivity implements MyPreferenceFragment.Callback {
private static final String TAG_NESTED = "TAG_NESTED";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_settings);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
if (toolbar != null) {
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
if (savedInstanceState == null) {
getFragmentManager().beginTransaction()
.add(R.id.contentSettings, new MyPreferenceFragment())
.commit();
}
}
@Override
public void onBackPressed() {
// this if statement is necessary to navigate through nested and main fragments
if (getFragmentManager().getBackStackEntryCount() == 0) {
super.onBackPressed();
} else {
getFragmentManager().popBackStack();
}
}
@Override
public void onNestedPreferenceSelected(int key) {
getFragmentManager().beginTransaction().replace(R.id.contentSettings, NestedPreferenceFragment.newInstance(key), TAG_NESTED).addToBackStack(TAG_NESTED).commit();
}
}
<强> MyPreferenceFragment.java 强>
// The main preference fragment class
public class MyPreferenceFragment extends PreferenceFragment implements Preference.OnPreferenceClickListener {
private Callback mCallback;
private static final String KEY_1 = "NESTED_KEY1";
private static final String KEY_2 = "NESTED_KEY2";
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
if (activity instanceof Callback) {
mCallback = (Callback) activity;
} else {
throw new IllegalStateException("Owner must implement Callback interface");
}
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Load the preferences from an XML resource
addPreferencesFromResource(R.xml.main_preferences);
// add listeners for non-default actions
Preference preference = findPreference(KEY_1);
preference.setOnPreferenceClickListener(this);
preference = findPreference(KEY_2);
preference.setOnPreferenceClickListener(this);
}
@Override
public boolean onPreferenceClick(Preference preference) {
// here you should use the same keys as you used in the xml-file
if (preference.getKey().equals(KEY_1)) {
mCallback.onNestedPreferenceSelected(NestedPreferenceFragment.NESTED_SCREEN_1_KEY);
}
if (preference.getKey().equals(KEY_2)) {
mCallback.onNestedPreferenceSelected(NestedPreferenceFragment.NESTED_SCREEN_2_KEY);
}
return false;
}
public interface Callback {
public void onNestedPreferenceSelected(int key);
}
}
<强> NestedPreferencesFragment.java 强>
public class NestedPreferenceFragment extends PreferenceFragment {
public static final int NESTED_SCREEN_1_KEY = 1;
public static final int NESTED_SCREEN_2_KEY = 2;
private static final String TAG_KEY = "NESTED_KEY";
public static NestedPreferenceFragment newInstance(int key) {
NestedPreferenceFragment fragment = new NestedPreferenceFragment();
// supply arguments to bundle.
Bundle args = new Bundle();
args.putInt(TAG_KEY, key);
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
checkPreferenceResource();
}
private void checkPreferenceResource() {
int key = getArguments().getInt(TAG_KEY);
// Load the preferences from an XML resource
switch (key) {
case NESTED_SCREEN_1_KEY:
addPreferencesFromResource(R.xml.nested_screen1_preferences);
break;
case NESTED_SCREEN_2_KEY:
addPreferencesFromResource(R.xml.nested_screen2_preferences);
break;
default:
break;
}
}
}
答案 1 :(得分:7)
这是我的解决方案,它的灵感来自原始答案,但并不复杂。也许它会帮助别人......
layout/settings.xml
:
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent" >
<include
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
layout="@layout/toolbar" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/content"
android:layout_below="@+id/toolbar"/>
</RelativeLayout>
类:
public class SettingsActivity extends ActionBarActivity {
@Override
protected void onCreate( Bundle savedInstanceState ) {
setContentView( R.layout.settings );
super.onCreate( savedInstanceState );
initializeSupportActionBar();
getFragmentManager().beginTransaction().replace( R.id.content, new MainFragment() ).commit();
}
@Override
public void onBackPressed() {
if( !getFragmentManager().popBackStackImmediate() ) super.onBackPressed();
}
}
public class MainFragment extends PreferenceFragment {
public MainFragment() {}
@Override
public void onCreate( Bundle savedInstanceState ) {
super.onCreate( savedInstanceState );
addPreferencesFromResource( R.xml.pref_main );
// "nested" is the <Preference android:key="nested" android:persistent="false"/>`
findPreference( "nested" ).setOnPreferenceClickListener( new OnPreferenceClickListener() {
@Override public boolean onPreferenceClick( Preference preference ) {
getFragmentManager().beginTransaction().replace( R.id.content, new NestedFragment() ).addToBackStack( NestedFragment.class.getSimpleName() ).commit();
return true;
}
} );
}
public class NestedFragment extends PreferenceFragment {
...
}
我在4.3
和5.0.2
上对其进行了测试,并且对嵌套级别没有任何限制
答案 2 :(得分:0)
在我的解决方案中,您只需要一个AppCompatActivity
和一个PreferenceFragement
,但需要多个XML文件,每个文件只有一个PreferenceScreens
级别。
XML文件列表
此代码用于一个子级别(为了简单起见并获得想法),但您可以轻松地将其扩展为具有PreferenceScreens
的任意子级别。
<强> SettingsFragment.java 强>
public class SettingsFragment extends PreferenceFragment
{
private int xmlId;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
xmlId = R.xml.preferences;
addPreferencesFromResource(xmlId);
}
public void changePrefScreen(int xmlId, int titleId)
{
this.xmlId = xmlId;
((AppCompatActivity)getActivity()).getSupportActionBar().setTitle(getActivity().getResources().getString(titleId));
getPreferenceScreen().removeAll();
addPreferencesFromResource(xmlId);
}
// will be called by SettingsActivity (Host Activity)
public void onUpButton()
{
if(xmlId == R.xml.preferences) // in top-level
{
// Switch to MainActivity
Intent intent = new Intent(getActivity(), MainActivity.class);
startActivity(intent);
}
else // in sub-level
{
changePrefScreen(R.xml.preferences, R.string.settings);
}
}
@Override
public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference)
{
String key = preference.getKey();
//
// Top level PreferenceScreen
//
if(key.equals("top_key_0"))
{
changePrefScreen(R.xml.download_preference_screen, R.string.download_database); // descend into second level
}
// ...
//
// Second level PreferenceScreens
//
if (key.equals("second_level_key_0"))
{
// do something...
}
// ...
}
<强> SettingsActivity.java 强>
public class SettingsActivity extends AppCompatActivity
{
SettingsFragment settingsFragment;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
settingsFragment = new SettingsFragment();
// Display the fragment as the main content.
getFragmentManager().beginTransaction()
.replace(android.R.id.content, settingsFragment)
.commit();
}
//
// Handle what happens on up button
//
@Override
public boolean onOptionsItemSelected(MenuItem item)
{
switch (item.getItemId())
{
case android.R.id.home:
settingsFragment.onUpButton();
return true;
}
return true;
}
// ...
}
从技术上讲,它应适用于PreferenceFragment
可用的所有Android版本。
答案 3 :(得分:0)
由于问题来自您仍然在同一活动/片段中的部分,而嵌套的pref屏幕只是一个对话框,您可以执行以下操作:
从对话框中获取根视图:
(PreferenceScreen)preference).getDialog().getWindow()
.getDecorView().getRootView());
递归搜索,直到找到一个存根视图(有一个,不幸的是我不知道android.R.id.xxxxx
)并设置你需要的标题作为标题,看起来像工具栏(你可以膨胀工具栏) :
private Toolbar toolbar;
public void findViewStub(ViewGroup viewGroup) {
int childCount = viewGroup.getChildCount();
for (int i = 0; i < childCount; i++) {
View childView = viewGroup.getChildAt(i);
if( childView instanceof ViewStub){
((ViewStub)childView).setLayoutResource(R.layout.your_title_layout);
toolbar = ((ViewStub)childView).inflate();
}
if (childView instanceof ViewGroup) {
findViewStub((ViewGroup) childView);
}
}
}
toolbar.setNavigationIcon();
toolbar.setNavigationOnClickListener();
toolbar.setTitle();
在布局中,您只能放置工具栏。并设置后退图标。注册单击它并引用片段,单击即可关闭对话框。您已设置标题等。