Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Keep the actionbar displayed in when changing PreferenceScreen

I'm trying to display a actionbar in my preference screen. In order to do so I added the following code in my 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);
    }
}

then the rest of my code in PreferencesFragment. This works fine, 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. Any idea how to keep the actionbar displayed (and updated with the PreferenceScreen label) ?

Edit: Looking at the PreferenceScreen code it looks like a full screen Dialog is opened when the PreferenceScreen is clicked on. Because my preference has a title the Dialog should display a title as well... but it doesn't

    // 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);
    }
like image 679
user1026605 Avatar asked Mar 30 '15 22:03

user1026605


People also ask

What is Preference screen in android?

Use the AndroidX Preference Library for consistent behavior across all devices. For more information on using the AndroidX Preference Library see Settings. Represents a top-level Preference that is the root of a Preference hierarchy. A PreferenceActivity points to an instance of this class to show the preferences.


3 Answers

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);
    }
}
like image 104
user1026605 Avatar answered Oct 09 '22 14:10

user1026605


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.

like image 36
szym Avatar answered Oct 09 '22 14:10

szym


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.

like image 1
Johannes Muenichsdorfer Avatar answered Oct 09 '22 13:10

Johannes Muenichsdorfer