更改 PreferenceScreen 时保持操作栏显示
Keep the actionbar displayed in when changing PreferenceScreen
我正在尝试在我的首选项屏幕中显示操作栏。
为此,我在 SettingActivity
中添加了以下代码
public class PreferencesActivity extends ActionBarActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.preferences_activity);
getFragmentManager().beginTransaction()
.replace(R.id.container, new PreferencesFragment()).commit();
getSupportActionBar().setDisplayOptions(ActionBar.DISPLAY_SHOW_TITLE | ActionBar.DISPLAY_SHOW_HOME | ActionBar.DISPLAY_HOME_AS_UP);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
}
然后是我在 PreferencesFragment 中的其余代码。
这工作正常,但只要我按下 PreferenceScreen 首选项,操作栏就会被隐藏。如果我返回首选项主屏幕,我可以再次看到它。
知道如何保持操作栏显示(并使用 PreferenceScreen 标签更新)吗?
编辑:查看 PreferenceScreen 代码时,它看起来像是在单击 PreferenceScreen 时打开全屏对话框。因为我的首选项有一个标题,对话框也应该显示一个标题...但它没有
// Set the title bar if title is available, else no title bar
final CharSequence title = getTitle();
Dialog dialog = mDialog = new Dialog(context, context.getThemeResId());
if (TextUtils.isEmpty(title)) {
dialog.getWindow().requestFeature(Window.FEATURE_NO_TITLE);
} else {
dialog.setTitle(title);
}
我制作了一个在首选项中有操作栏的应用程序 activity。我似乎看不出这样做的关键,尽管我确实记得我花了一些时间才把它弄好。
看来我们的代码很相似。唯一引起我注意的是这个导入:import android.support.v7.app.ActionBarActivity;
如果有帮助请告诉我
public class SettingsActivity extends ActionBarActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getFragmentManager().beginTransaction().replace(android.R.id.content, new PrefsFragment() ).commit();
} // End of onCreate
static public class PrefsFragment extends PreferenceFragment {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences); // Load the preferences from an XML resource
}
} // end of PrefsFragment
}
补充:你的styles.xml里有这个吗?
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
</style>
but as soon as I press on a PreferenceScreen preference, the actionbar is hidden. If I go back to the preference main screen I can see it again.
我猜你在点击首选项时启动了一个新的 activity
您的偏好片段应如下所示
public static class PreferencesFragment extends PreferenceFragment {
public PlaceholderFragment() {
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.your_preferences);
}
}
然后采样 your_preferences 如下
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="fill_parent"
android:layout_width="fill_parent" >
<PreferenceCategory
android:title="@string/pref_category_title">
<PreferenceScreen
android:title="@string/title"
android:summary="@string/summary">
<intent
android:targetClass="com.your.package.Youractivity "
android:targetPackage="com.your.package"/>
</PreferenceScreen>
<PreferenceScreen
android:title="@string/another_title">
<intent
android:targetClass="com.your.package.activity2"
android:targetPackage="com.your.package.activity"/>
</PreferenceScreen>
</PreferenceCategory>
最后你的activity 应该从 ActionBarActivity
扩展
public class Youractivity extends ActionBarActivity {
}
上面的代码对我有用。
正如您在问题中提到的,全屏 Dialog
可能是个问题。
尝试将 Dialog
样式更改为:
<style name="Theme.Holo.Dialog">
或具有这些属性的样式:
<item name="windowActionBar">true</item>
<item name="windowNoTitle">false</item>
Here 您可以阅读如何获取对 Dialog
的引用。
注:仅适用于API>=14
Source1 and Source2
PreferenceActivity1.java
public class PreferenceActivity1 extends android.preference.PreferenceActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.pref1);
}
@Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
LinearLayout root = (LinearLayout)findViewById(android.R.id.list).getParent().getParent().getParent();
Toolbar bar = (Toolbar) LayoutInflater.from(this).inflate(R.layout.settings_toolbar, root, false);
root.addView(bar, 0); // insert at top
bar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
finish();
}
});
}
}
PreferenceActivity2.java
public class PreferenceActivity2 extends android.preference.PreferenceActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.pref2);
}
@Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
LinearLayout root = (LinearLayout)findViewById(android.R.id.list).getParent().getParent().getParent();
Toolbar bar = (Toolbar) LayoutInflater.from(this).inflate(R.layout.settings_toolbar, root, false);
root.addView(bar, 0); // insert at top
bar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
finish();
}
});
}
}
settings_toolbar.xml(布局)
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.Toolbar
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/toolbar"
app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="?attr/actionBarSize"
app:navigationContentDescription="@string/abc_action_bar_up_description"
android:background="?attr/colorPrimary"
app:navigationIcon="?attr/homeAsUpIndicator"
app:title="@string/app_name"
/>
pref1.xml(xml)
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
android:theme="@android:style/Theme.Light" >
<PreferenceCategory android:title="Main Preferences" >
<CheckBoxPreference
android:key="wifi enabled"
android:title="WiFi" />
</PreferenceCategory>
<PreferenceScreen
android:key="key1"
android:summary=""
android:title="Wifi Settings" >
<intent
android:action="android.intent.action.VIEW"
android:targetClass="com.example.PreferenceActivity2"
android:targetPackage="com.example" />
</PreferenceScreen>
</PreferenceScreen>
pref2.xml(xml)
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
android:theme="@android:style/Theme.Light" >
<PreferenceCategory android:title="Wifi Settings" >
<CheckBoxPreference
android:key="prefer wifi"
android:title="Prefer WiFi" />
</PreferenceCategory>
</PreferenceScreen>
清单
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name" >
<activity
android:name="com.example.PreferenceActivity1"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name="com.example.PreferenceActivity2"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
</application>
结果
我终于设法找到一种方法来做到这一点。
这有点丑陋,但它有效。
首先,我向 preferences.xml 文件中的每个 PreferenceScreen 定义添加相同的 Intent(确保更新额外参数的值)
<PreferenceScreen
android:key="pref1"
android:summary="Summary1"
android:title="Title1" >
<intent
android:action="android.intent.action.VIEW"
android:targetPackage="my.package"
android:targetClass="my.package.activity.PreferencesActivity" >
<extra android:name="page" android:value="pref1" />
</intent>
...
</PreferenceScreen>
顺便说一句 my.package.activity.PreferencesActivity 是我目前的偏好 Activity
然后我在清单中添加一个 intent-filter
<activity
android:name=".activity.PreferencesActivity"
android:configChanges="keyboardHidden|orientation|screenSize"
android:label="@string/settings" >
<intent-filter android:label="Pref" >
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.PREFERENCE" />
</intent-filter>
</activity>
我在首选项中添加了一些代码Activity来处理这个
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.preferences_activity);
this.fragment = new PreferencesFragment();
this.fragment.setActivityIntent(getIntent());
getFragmentManager().beginTransaction()
.replace(R.id.container, this.fragment).commit();
}
最后,我在 PreferencesFragment 中添加了以下代码 class
public void setActivityIntent(final Intent activityIntent) {
if (activityIntent != null) {
if (Intent.ACTION_VIEW.equals(activityIntent.getAction())) {
if (intent.getExtras() != null) {
final String page = intent.getExtras().getString("page");
if (!TextUtils.isEmpty(page)) {
openPreferenceScreen(page);
}
}
}
}
private void openPreferenceScreen(final String screenName) {
final Preference pref = findPreference(screenName);
if (pref instanceof PreferenceScreen) {
final PreferenceScreen preferenceScreen = (PreferenceScreen) pref;
((PreferencesActivity) getActivity()).setTitle(preferenceScreen.getTitle());
setPreferenceScreen((PreferenceScreen) pref);
}
}
有同样的问题。嵌套的 PreferenceScreen
没有 ActionBar。单步执行代码后,似乎是由 AppCompatActivity
和 PreferenceScreen
.
之间的冲突引起的
一方面,AppCompatActivity
提供了自己的操作栏,因此需要一个从 Theme.AppCompat
下降的主题,该主题指定 windowNoTitle = true
某处(无法准确指出位置)。另一方面——PreferenceScreen
使用平台 Dialog
和 activity 主题(而不是 sub-theme,例如 dialogTheme
)。可能是一个错误。
如果您不关心 Theme.AppCompat
,这里有一个适用于 API 21+ 的简单解决方法:
- 使用
android.preference.PreferenceActivity
作为 class 的基础 activity
为此创建一个主题 activity:
<!-- This theme is used to show ActionBar on sub-PreferenceScreens -->
<style name="PreferenceTheme" parent="">
<item name="android:windowActionBar">true</item>
<item name="android:windowNoTitle">false</item>
</style>
- 在
AndroidManifest.xml
中为此 activity 指定 android:theme="@style/PreferenceTheme"
您将获得的更像是标准 window 标题,而不是完整的 ActionBar。我还没有弄清楚如何添加工作后退按钮等。
如果您想与 AppCompatActivity
和相关主题保持兼容,您需要在 activity window 上请求 FEATURE_NO_TITLE
。否则,您将在 top-level PreferenceScreen
.
中得到两个操作栏(顶部的 built-in 和底部的支撑)
由于google遗憾的是直到现在才修复它,实际上有一个更简单的解决方案:
将您的 SettingsActivity class 设置为仅从 "Activity".
扩展
public class SettingsActivity extends Activity { ...
在您的 v21/styles 文件夹中为您的 SettingsActivty 创建一个新主题,并将父级设置为 "Theme.Material.*"
<style name="CustomThemeSettings" parent="android:Theme.Material">
<item name="android:colorPrimary">@color/...</item>
<item name="android:colorPrimaryDark">@color/...</item>
<item name="android:colorAccent">@color/...</item>
</style>
在 Manifest.xml 文件中设置新主题:
<activity
android:name=".SettingsActivity"
android:label="@string/title_activity_settingsactivity"
android:theme="@style/CustomThemeSettings" >
</activity>
它很管用:)
(可选)如果您想为旧设备提供Material设计支持
您可以将 SettingsActivity 放在 v21+ 文件夹中并创建另一个
具有父 AppCompat 的旧设备的 SettingsActivity。
我创建了 PreferenceCompatActivity
,它是旧 PreferenceActivity
的 AndroidX 兼容的直接替代品。
它在内部使用了兼容片段。请务必仅使用 androidx.preference.XXX
类 而不是 android.preference.XXX
的导入。
public class PreferenceCompatActivity extends AppCompatActivity implements AppCompatCallback, PreferenceFragmentCompat.OnPreferenceStartScreenCallback {
private PreferenceFragmentCompat fragment;
public void addPreferencesFromResource(@XmlRes int preferencesResId) {
fragment = new RootPreferencesFragment(preferencesResId);
getSupportFragmentManager().beginTransaction().replace(android.R.id.content, fragment).commitNow();
}
public PreferenceManager getPreferenceManager() {
return fragment.getPreferenceManager();
}
public PreferenceScreen getPreferenceScreen() {
return fragment.getPreferenceScreen();
}
public Preference findPreference(CharSequence key) {
return fragment.findPreference(key);
}
@Override
public boolean onPreferenceStartScreen(PreferenceFragmentCompat caller, PreferenceScreen pref) {
LowerPreferencesFragment lowerFragment = new LowerPreferencesFragment(pref);
getSupportFragmentManager().beginTransaction().replace(android.R.id.content, lowerFragment).addToBackStack("lower").commit();
return true;
}
public static class RootPreferencesFragment extends PreferenceFragmentCompat {
private int preferencesResId;
public RootPreferencesFragment(int preferencesResId) {
this.preferencesResId = preferencesResId;
}
@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
addPreferencesFromResource(preferencesResId);
}
}
public static class LowerPreferencesFragment extends PreferenceFragmentCompat {
private PreferenceScreen prefs;
public LowerPreferencesFragment() {
}
public LowerPreferencesFragment(PreferenceScreen prefs) {
this.prefs = prefs;
}
@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
if (prefs != null) {
setPreferenceScreen(prefs);
prefs = null;
}
}
}
}
我正在尝试在我的首选项屏幕中显示操作栏。 为此,我在 SettingActivity
中添加了以下代码public class PreferencesActivity extends ActionBarActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.preferences_activity);
getFragmentManager().beginTransaction()
.replace(R.id.container, new PreferencesFragment()).commit();
getSupportActionBar().setDisplayOptions(ActionBar.DISPLAY_SHOW_TITLE | ActionBar.DISPLAY_SHOW_HOME | ActionBar.DISPLAY_HOME_AS_UP);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
}
然后是我在 PreferencesFragment 中的其余代码。 这工作正常,但只要我按下 PreferenceScreen 首选项,操作栏就会被隐藏。如果我返回首选项主屏幕,我可以再次看到它。 知道如何保持操作栏显示(并使用 PreferenceScreen 标签更新)吗?
编辑:查看 PreferenceScreen 代码时,它看起来像是在单击 PreferenceScreen 时打开全屏对话框。因为我的首选项有一个标题,对话框也应该显示一个标题...但它没有
// Set the title bar if title is available, else no title bar final CharSequence title = getTitle(); Dialog dialog = mDialog = new Dialog(context, context.getThemeResId()); if (TextUtils.isEmpty(title)) { dialog.getWindow().requestFeature(Window.FEATURE_NO_TITLE); } else { dialog.setTitle(title); }
我制作了一个在首选项中有操作栏的应用程序 activity。我似乎看不出这样做的关键,尽管我确实记得我花了一些时间才把它弄好。
看来我们的代码很相似。唯一引起我注意的是这个导入:import android.support.v7.app.ActionBarActivity;
如果有帮助请告诉我
public class SettingsActivity extends ActionBarActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getFragmentManager().beginTransaction().replace(android.R.id.content, new PrefsFragment() ).commit();
} // End of onCreate
static public class PrefsFragment extends PreferenceFragment {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences); // Load the preferences from an XML resource
}
} // end of PrefsFragment
}
补充:你的styles.xml里有这个吗?
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
</style>
but as soon as I press on a PreferenceScreen preference, the actionbar is hidden. If I go back to the preference main screen I can see it again.
我猜你在点击首选项时启动了一个新的 activity
您的偏好片段应如下所示
public static class PreferencesFragment extends PreferenceFragment {
public PlaceholderFragment() {
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.your_preferences);
}
}
然后采样 your_preferences 如下
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="fill_parent"
android:layout_width="fill_parent" >
<PreferenceCategory
android:title="@string/pref_category_title">
<PreferenceScreen
android:title="@string/title"
android:summary="@string/summary">
<intent
android:targetClass="com.your.package.Youractivity "
android:targetPackage="com.your.package"/>
</PreferenceScreen>
<PreferenceScreen
android:title="@string/another_title">
<intent
android:targetClass="com.your.package.activity2"
android:targetPackage="com.your.package.activity"/>
</PreferenceScreen>
</PreferenceCategory>
最后你的activity 应该从 ActionBarActivity
扩展 public class Youractivity extends ActionBarActivity {
}
上面的代码对我有用。
正如您在问题中提到的,全屏 Dialog
可能是个问题。
尝试将 Dialog
样式更改为:
<style name="Theme.Holo.Dialog">
或具有这些属性的样式:
<item name="windowActionBar">true</item>
<item name="windowNoTitle">false</item>
Here 您可以阅读如何获取对 Dialog
的引用。
注:仅适用于API>=14
Source1 and Source2
PreferenceActivity1.java
public class PreferenceActivity1 extends android.preference.PreferenceActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.pref1);
}
@Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
LinearLayout root = (LinearLayout)findViewById(android.R.id.list).getParent().getParent().getParent();
Toolbar bar = (Toolbar) LayoutInflater.from(this).inflate(R.layout.settings_toolbar, root, false);
root.addView(bar, 0); // insert at top
bar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
finish();
}
});
}
}
PreferenceActivity2.java
public class PreferenceActivity2 extends android.preference.PreferenceActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.pref2);
}
@Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
LinearLayout root = (LinearLayout)findViewById(android.R.id.list).getParent().getParent().getParent();
Toolbar bar = (Toolbar) LayoutInflater.from(this).inflate(R.layout.settings_toolbar, root, false);
root.addView(bar, 0); // insert at top
bar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
finish();
}
});
}
}
settings_toolbar.xml(布局)
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.Toolbar
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/toolbar"
app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="?attr/actionBarSize"
app:navigationContentDescription="@string/abc_action_bar_up_description"
android:background="?attr/colorPrimary"
app:navigationIcon="?attr/homeAsUpIndicator"
app:title="@string/app_name"
/>
pref1.xml(xml)
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
android:theme="@android:style/Theme.Light" >
<PreferenceCategory android:title="Main Preferences" >
<CheckBoxPreference
android:key="wifi enabled"
android:title="WiFi" />
</PreferenceCategory>
<PreferenceScreen
android:key="key1"
android:summary=""
android:title="Wifi Settings" >
<intent
android:action="android.intent.action.VIEW"
android:targetClass="com.example.PreferenceActivity2"
android:targetPackage="com.example" />
</PreferenceScreen>
</PreferenceScreen>
pref2.xml(xml)
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
android:theme="@android:style/Theme.Light" >
<PreferenceCategory android:title="Wifi Settings" >
<CheckBoxPreference
android:key="prefer wifi"
android:title="Prefer WiFi" />
</PreferenceCategory>
</PreferenceScreen>
清单
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name" >
<activity
android:name="com.example.PreferenceActivity1"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name="com.example.PreferenceActivity2"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
</application>
结果
我终于设法找到一种方法来做到这一点。 这有点丑陋,但它有效。
首先,我向 preferences.xml 文件中的每个 PreferenceScreen 定义添加相同的 Intent(确保更新额外参数的值)
<PreferenceScreen
android:key="pref1"
android:summary="Summary1"
android:title="Title1" >
<intent
android:action="android.intent.action.VIEW"
android:targetPackage="my.package"
android:targetClass="my.package.activity.PreferencesActivity" >
<extra android:name="page" android:value="pref1" />
</intent>
...
</PreferenceScreen>
顺便说一句 my.package.activity.PreferencesActivity 是我目前的偏好 Activity
然后我在清单中添加一个 intent-filter
<activity
android:name=".activity.PreferencesActivity"
android:configChanges="keyboardHidden|orientation|screenSize"
android:label="@string/settings" >
<intent-filter android:label="Pref" >
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.PREFERENCE" />
</intent-filter>
</activity>
我在首选项中添加了一些代码Activity来处理这个
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.preferences_activity);
this.fragment = new PreferencesFragment();
this.fragment.setActivityIntent(getIntent());
getFragmentManager().beginTransaction()
.replace(R.id.container, this.fragment).commit();
}
最后,我在 PreferencesFragment 中添加了以下代码 class
public void setActivityIntent(final Intent activityIntent) {
if (activityIntent != null) {
if (Intent.ACTION_VIEW.equals(activityIntent.getAction())) {
if (intent.getExtras() != null) {
final String page = intent.getExtras().getString("page");
if (!TextUtils.isEmpty(page)) {
openPreferenceScreen(page);
}
}
}
}
private void openPreferenceScreen(final String screenName) {
final Preference pref = findPreference(screenName);
if (pref instanceof PreferenceScreen) {
final PreferenceScreen preferenceScreen = (PreferenceScreen) pref;
((PreferencesActivity) getActivity()).setTitle(preferenceScreen.getTitle());
setPreferenceScreen((PreferenceScreen) pref);
}
}
有同样的问题。嵌套的 PreferenceScreen
没有 ActionBar。单步执行代码后,似乎是由 AppCompatActivity
和 PreferenceScreen
.
一方面,AppCompatActivity
提供了自己的操作栏,因此需要一个从 Theme.AppCompat
下降的主题,该主题指定 windowNoTitle = true
某处(无法准确指出位置)。另一方面——PreferenceScreen
使用平台 Dialog
和 activity 主题(而不是 sub-theme,例如 dialogTheme
)。可能是一个错误。
如果您不关心 Theme.AppCompat
,这里有一个适用于 API 21+ 的简单解决方法:
- 使用
android.preference.PreferenceActivity
作为 class 的基础 activity 为此创建一个主题 activity:
<!-- This theme is used to show ActionBar on sub-PreferenceScreens --> <style name="PreferenceTheme" parent=""> <item name="android:windowActionBar">true</item> <item name="android:windowNoTitle">false</item> </style>
- 在
AndroidManifest.xml
中为此 activity 指定
android:theme="@style/PreferenceTheme"
您将获得的更像是标准 window 标题,而不是完整的 ActionBar。我还没有弄清楚如何添加工作后退按钮等。
如果您想与 AppCompatActivity
和相关主题保持兼容,您需要在 activity window 上请求 FEATURE_NO_TITLE
。否则,您将在 top-level PreferenceScreen
.
由于google遗憾的是直到现在才修复它,实际上有一个更简单的解决方案:
将您的 SettingsActivity class 设置为仅从 "Activity".
扩展public class SettingsActivity extends Activity { ...
在您的 v21/styles 文件夹中为您的 SettingsActivty 创建一个新主题,并将父级设置为 "Theme.Material.*"
<style name="CustomThemeSettings" parent="android:Theme.Material"> <item name="android:colorPrimary">@color/...</item> <item name="android:colorPrimaryDark">@color/...</item> <item name="android:colorAccent">@color/...</item> </style>
在 Manifest.xml 文件中设置新主题:
<activity android:name=".SettingsActivity" android:label="@string/title_activity_settingsactivity" android:theme="@style/CustomThemeSettings" > </activity>
它很管用:)
(可选)如果您想为旧设备提供Material设计支持
您可以将 SettingsActivity 放在 v21+ 文件夹中并创建另一个 具有父 AppCompat 的旧设备的 SettingsActivity。
我创建了 PreferenceCompatActivity
,它是旧 PreferenceActivity
的 AndroidX 兼容的直接替代品。
它在内部使用了兼容片段。请务必仅使用 androidx.preference.XXX
类 而不是 android.preference.XXX
的导入。
public class PreferenceCompatActivity extends AppCompatActivity implements AppCompatCallback, PreferenceFragmentCompat.OnPreferenceStartScreenCallback {
private PreferenceFragmentCompat fragment;
public void addPreferencesFromResource(@XmlRes int preferencesResId) {
fragment = new RootPreferencesFragment(preferencesResId);
getSupportFragmentManager().beginTransaction().replace(android.R.id.content, fragment).commitNow();
}
public PreferenceManager getPreferenceManager() {
return fragment.getPreferenceManager();
}
public PreferenceScreen getPreferenceScreen() {
return fragment.getPreferenceScreen();
}
public Preference findPreference(CharSequence key) {
return fragment.findPreference(key);
}
@Override
public boolean onPreferenceStartScreen(PreferenceFragmentCompat caller, PreferenceScreen pref) {
LowerPreferencesFragment lowerFragment = new LowerPreferencesFragment(pref);
getSupportFragmentManager().beginTransaction().replace(android.R.id.content, lowerFragment).addToBackStack("lower").commit();
return true;
}
public static class RootPreferencesFragment extends PreferenceFragmentCompat {
private int preferencesResId;
public RootPreferencesFragment(int preferencesResId) {
this.preferencesResId = preferencesResId;
}
@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
addPreferencesFromResource(preferencesResId);
}
}
public static class LowerPreferencesFragment extends PreferenceFragmentCompat {
private PreferenceScreen prefs;
public LowerPreferencesFragment() {
}
public LowerPreferencesFragment(PreferenceScreen prefs) {
this.prefs = prefs;
}
@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
if (prefs != null) {
setPreferenceScreen(prefs);
prefs = null;
}
}
}
}