Keep the actionbar displayed in when changing PreferenceScreen

Since google sadly didn't fixed it until now, there is actually one much easier solution:

  1. Set your SettingsActivity class to extend from just "Activity".

    public class SettingsActivity extends Activity { ...

  2. Create a new Theme in your v21/styles folder for your SettingsActivty and set the parent to "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>

  3. Set your new theme in your Manifest.xml file:

    <activity android:name=".SettingsActivity" android:label="@string/title_activity_settingsactivity" android:theme="@style/CustomThemeSettings" > </activity>

  4. It just works :)

  5. (Optional) If you want to provide Material Design support for older Devices
    you can put the SettingsActivity in an v21+ folder and create a other SettingsActivity for older devices which has the parent AppCompat.


I finally managed to find a way to do this. It's kind of ugly but it works.

First I add an the same Intent to every PreferenceScreen definition in my preferences.xml file (make sure to update the value of the extra parameter)

        <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>

BTW my.package.activity.PreferencesActivity is my current Preference Activity

Then I add an intent-filter in the Manifest

        <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>

I add some code in the PreferenceActivity to handle this

   @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();
    }

Finally I add the following code in my 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);
    }
}

Had the same issue. Nested PreferenceScreens did not have an ActionBar. After stepping through the code, it appears to be caused by a conflict between AppCompatActivity and PreferenceScreen.

On one hand AppCompatActivity provides its own action bar, and therefore requires a theme descending from Theme.AppCompat which specifies windowNoTitle = true somewhere (could not pinpoint exactly where). On the other -- PreferenceScreen uses platform Dialog with the activity theme (rather than sub-theme, e.g., dialogTheme). Could be a bug.

If you don't care about Theme.AppCompat, here's a simple workaround that works on API 21+:

  • use android.preference.PreferenceActivity as the base class for your activity
  • create a theme for that 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>
    
  • specify android:theme="@style/PreferenceTheme" for this activity in the AndroidManifest.xml

What you'll get is more like a standard window title than a full ActionBar. I haven't yet figured out how to add a working back button, etc.

If you want to remain compatible with AppCompatActivity and the related themes, you'll need to request FEATURE_NO_TITLE on the activity window. Otherwise, you'll end up with two action bars (the built-in on top, and the support on bottom) in the top-level PreferenceScreen.