My inner PreferenceScreen of PreferenceFragmentCompat is not showing, or seems to ignore tapping events.
I created MyPreferenceFragment
that extends PreferenceFragmentCompat
public class MyPreferenceFragment extends PreferenceFragmentCompat {
@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
addPreferencesFromResource(R.xml.preferences);
}
}
then I changed my theme at styles.xml
like
<style name="AppTheme" parent="@style/Theme.AppCompat.Light">
<item name="preferenceTheme">@style/PreferenceThemeOverlay</item>
</style>
And finally create my preferences.xml
file like
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<CheckBoxPreference android:title="Check Me"/>
<PreferenceScreen android:title="My Screen"> <!-- This is not opening -->
<EditTextPreference android:title="Edit text" />
</PreferenceScreen>
</PreferenceScreen>
At the build.gradle
I have added both:
compile 'com.android.support:appcompat-v7:23.0.1'
compile 'com.android.support:preference-v7:23.0.1'
code of the Activity
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
activity_main.xml
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/fragment"
android:name="com.mando.preferenceapp.MyPreferenceFragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />
Testing the above code I cannot open / get into the preference screen. Am I missing something? Why this isn't working?
Another solution is to track the preference screens yourself and use the PreferenceFragmentCompat api
Here's the basic solution. (It doesn't cover all the edge cases, see advanced solution below)
Ensure you have configChanges="orientation" to prevent create/destroy
In the Activity you want to keep a Stack of PreferenceScreens and push/pop as needed
Optional: In your Fragment that extends PreferenceFragmentCompat, add setRetainInstance(true). (Note that without this it will likely work also, but it 'could' break occasionally. If you set 'Don't keep Activities' to true, and you'll see that it will get collected)
That's it! Except that if you want to cover edge cases...
Advanced Solution (If you set 'Don't Keep Activities to True, you'll need to ensure you can rebuild everything from savedInstanceState)
Note that the accepted answer doesn't actually preserve state.
Full Advanced Solution using PreferenceFragmentCompat api and preserving the PreferenceScreen stack
You can also handle all this in your Fragment instead of the Activity. Here's a gist of that https://gist.github.com/aaronvargas/0f210ad8643b512efda4acfd524e1232
After spending many many hours with tries, searching and thankfully with some assistance from the creators of the support library. I've managed to make it work.
Step 1.
Activity
Tips.
xml
you will have crashes on orientation changes.onCreate
so as to avoid losing your fragment when inside a preference screen.PreferenceFragmentCompat.OnPreferenceStartScreenCallback
and recreate fragments of the same instance.Step 2.
PreferenceFragment
Tips.
setPreferencesFromResource
and take advantage of therootKey
of each screen. This way your code will be reused properly.findPreference
in your fragment it should havenull
checks as when you were in inner screens this will give you nothing.The thing that is missing now is the implementation of the back arrow in the actionbar (home action) but this never works by itself ;-)
I' also created a demo app wrapping all this code you can find it on github.
Based on @squirrel Intent solution, I made it work this way. It requires even less hacking.
Activity:
Fragment:
It is sad you need so much hacks in the support appcompat libraries for something that works flawlessly out-of-the-box in standard android.
I did it slightly differently, I'm launching a new activity for each screen. This seems to require less hacks: no need to mess with swapping fragments and background colors. You also get activity change animation as a bonus!
xml:
Solution is to start another fragment of the same class but with different root key. No Activity actions involved.