I was having trouble using the new Material Design toolbar in the support library on a Preference screen.
I have a settings.xml file as below:
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory
android:title="@string/AddingItems"
android:key="pref_key_storage_settings">
<ListPreference
android:key="pref_key_new_items"
android:title="@string/LocationOfNewItems"
android:summary="@string/LocationOfNewItemsSummary"
android:entries="@array/new_items_entry"
android:entryValues="@array/new_item_entry_value"
android:defaultValue="1"/>
</PreferenceCategory>
</PreferenceScreen>
The strings are defined elsewhere.
With the release of the Android Support Library 22.1.0 and the new AppCompatDelegate, here you can find a nice sample of an implementation of the PreferenceActivity with material support with backwards compatibility.
Update It works on nested screens too.
https://android.googlesource.com/platform/development/+/marshmallow-mr3-release/samples/Support7Demos/src/com/example/android/supportv7/app/AppCompatPreferenceActivity.java
I have a new (possibly neater) solution, that uses the
AppCompatPreferenceActivity
from the Support v7 samples. With this code in hand I created my own layout that includes a toolbar:Then, in my
AppCompatPreferenceActivity
, I alteredsetContentView
to create a my new layout, and place the provided layout inside myFrameLayout
:Then I just extend
AppCompatPreferenceActivity
, allowing me to callsetSupportActionBar((Toolbar) findViewById(R.id.toolbar))
, and inflate menu items in the toolbar as well. All while keeping the benefits of aPreferenceActivity
.I too have been looking for a solution to adding the v7 support toolbar (API 25) to the AppCompatPreferenceActivity (that is automatically created by AndroidStudio when adding a SettingsActivity). After reading several solutions and trying each of them out I struggled to get the generated PreferenceFragment examples to display with a toolbar as well.
A modified solution that sort of worked was from "Gabor".
One of the caveats I faced was 'onBuildHeaders' only fires once. If you turn a device (like a phone) sideways, the view recreates and the PreferenceActivity is left without a toolbar again, however the PreferenceFragments would retain theirs.
I tried using 'onPostCreate' to call 'setContentView', while this worked to recreate the toolbar when the orientation changed, PreferenceFragments would then be rendered blank.
What I have come up with leverages just about every tip and answer I could read about this subject. I hope others find it useful as well.
We'll start with the Java
First in (the generated) AppCompatPreferenceActivity.java I modified 'setSupportActionBar' like so:
Second, I created a new class named AppCompatPreferenceFragment.java (it is current an unused name, although it may not stay that way!):
This is the portion of Gabor's answer that worked.
Last, To get consistency we need to make some changes to SettingsActivity.java:
Some code has been left out of the activity for brevity. The key components here are 'onAttachedFragment', 'onPostCreate', and that the 'GeneralPreferenceFragment' now extends the custom 'AppCompatPreferenceFragment' instead of PreferenceFragment.
Code Summary: If a fragment is present, the fragment injects the new layout and calls the modified 'setSupportActionBar' function. If the fragment is not present, SettingsActivity injects the new layout on 'onPostCreate'
Now on to the XML (very simple):
activity_settings.xml:
app_bar_settings.xml:
content_settings.xml:
End Result:
If you want to use PreferenceHeaders you can use the following approach:
layout/activity_settings.xml
You can use whatever layout you prefer here, just make sure you adjust it in the Java code as well.
And finally, your file with headers (xml/pref_headers.xml)
I would like to continue the marked solution of James Cross, since after that there's a problem of closing only the active nested screen (PreferenceFragment) in the way to not close the SettingsActivity as well.
Actually it does work on all nested screens (so I don't understand the solution of Gábor that I tried without success, well it works until a certain point but it's a mess of multiple toolbars), because when the user click a sub preference screen, only the fragment is changed (see
<FrameLayout android:id="@+id/content_frame" .../>
) not the Toolbar that remains always active and visible, but a custom behavior should be implemented to close each fragment accordingly.In the main class
SettingsActivity
that extendsActionBarActivity
the following methods should be implemented. Note that privatesetupActionBar()
is called fromonCreate()
For the title of the chosen nested screen you should get the reference of your Toolbar and set the appropriate title with
toolbar.setTitle(R.string.pref_title_general);
(for instance).There's no need to implement the
getSupportActionBar()
in all PreferenceFragment since only the view of the fragment is changed at every commit, not the Toolbar;There's no need to create a fake ToolbarPreference class to add in each preference.xml (see Gábor's answer).
Here's a library I've made that is based on AOSP code, which adds tinting to both the preferences and the dialogs, adds an action bar, and supports all versions from API 7 :
https://github.com/AndroidDeveloperLB/MaterialPreferenceLibrary