PreferenceFragmentCompat requires preferenceTheme to be set
The sample project can be found here
The bugfix is available as a gradle dependency
Now one can use the library pretty easy. Here are quickest way to do so, but you should check out the README for more info.
1. Update your module's gradle file:
compile 'com.takisoft.fix:preference-v7:27.0.0.0'
2. Use the appropriate class as your fragment's base
You can use either PreferenceFragmentCompat
or PreferenceFragmentCompatDividers
.
(Watch out for the appropriate package name when importing PreferenceFragmentCompat
!)
3. Use the appropriate theme
Set your containing Activity's theme to a variant of @style/PreferenceFixTheme
, like NoActionBar, Light, etc.
For more info and usage tips, go to the project's page.
P.S. In this section you could find the detailed solution that led to creation of the library, but I decided to remove it because it might be confusing. If you're curious about the steps, you can still find them in the revision history of this answer.
Fragment Must specify preferenceTheme in theme onCreate
Thanks to the solution that @Panther suggested. All I had to do is to add this line <item name="preferenceTheme">@style/PreferenceThemeOverlay</item>
to my Application Theme and not just the theme of the individual activity that is showing my PreferenceFragment like that:
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
<item name="preferenceTheme">@style/PreferenceThemeOverlay</item>
</style>
Alternatively you can use
<item name="preferenceTheme">@style/PreferenceThemeOverlay.v14.Material</item>
to achieve modern material look.
java.lang.IllegalStateException: Must specify preferenceTheme in theme
I managed to fix it. The problem was my activity that was loading the fragment didn't have the theme set.
<activity android:name=".controllers.MainActivity"
android:theme="@style/AppTheme.Base" />
How to apply theme to preferencescreen
try this in your activity tag in manifest
:
<activity android:name=".MainActivity"
android:theme="@style/AppTheme">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
your activity
that was loading the preference fragment
didn't have the theme set.
Also set this in your Apptheme
<item name="preferenceTheme">@style/PreferenceThemeOverlay</item>
instead of:
<item name="android:preferenceStyle">@style/PreferenceThemeOverlay</item>
add this lines in your Apptheme
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
Theming PreferenceFragmentCompat
See this sample project here created for your specific case the the only problem for this solution is you have to create your preference from code cant use xml file to inflate and
for those who just want the gist of this solution is that use setLayoutResource() method to set layout and use custom layout i just copied the original layout and hardcoded colors according to @Bhuntupana need
val messagesCategory = PreferenceCategory(context).apply {
layoutResource = R.layout.sample_preference
key = "messages_category"
title = getString(R.string.messages_header)
screen.addPreference(this)
}
Update
use layout tag to specify layout resource to use like this
<EditTextPreference
android:layout="@layout/sample_preference"
app:key="signature"
app:title="@string/signature_title"
app:useSimpleSummaryProvider="true" />
sample_preference.xml
just copy of default layout preference_material.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?android:attr/selectableItemBackground"
android:baselineAligned="false"
android:clipToPadding="false"
android:gravity="center_vertical"
android:minHeight="?android:attr/listPreferredItemHeightSmall"
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
android:paddingLeft="?android:attr/listPreferredItemPaddingLeft"
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
android:paddingRight="?android:attr/listPreferredItemPaddingRight">
<include layout="@layout/image_frame" />
<RelativeLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:paddingTop="16dp"
android:paddingBottom="16dp">
<TextView
android:id="@android:id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="marquee"
android:singleLine="true"
android:textAppearance="?android:attr/textAppearanceListItem"
android:textColor="#FD0000" />
<TextView
android:id="@android:id/summary"
style="@style/PreferenceSummaryTextStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@android:id/title"
android:layout_alignStart="@android:id/title"
android:layout_alignLeft="@android:id/title"
android:layout_gravity="start"
android:maxLines="10"
android:textAlignment="viewStart"
android:textColor="#1F6F2B" />
</RelativeLayout>
<!-- Preference should place its actual preference widget here. -->
<LinearLayout
android:id="@android:id/widget_frame"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="end|center_vertical"
android:orientation="vertical"
android:paddingStart="16dp"
android:paddingLeft="16dp"
android:paddingEnd="0dp"
android:paddingRight="0dp" />
</LinearLayout>
PreferenceFragmentCompat adds margin to preference items
If you are using AndroidX, you can use Preference.setIconSpaceReserved(boolean iconSpaceReserved)
method.
So, you will have:
item_Confirmation.setIconSpaceReserved(false);
You can also check this answer.
New Preference support library incorrect theme at runtime
The problem, you're facing, is related to Context
and how its theming works. Your code retrieves a context by passing getActivity()
to the constructor, however, this is not the context you want. Here's the solution that applies the correct styles:
final Context ctx = getPreferenceManager().getContext();
for (...) {
final ListPreference p = new ListPreference(ctx);
// [...]
category.addPreference(p);
}
Explanation
Here's PreferenceFragmentCompat
's onCreate(...)
method:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
TypedValue tv = new TypedValue();
this.getActivity().getTheme().resolveAttribute(attr.preferenceTheme, tv, true);
int theme = tv.resourceId;
if(theme <= 0) {
throw new IllegalStateException("Must specify preferenceTheme in theme");
} else {
this.mStyledContext = new ContextThemeWrapper(this.getActivity(), theme);
this.mPreferenceManager = new PreferenceManager(this.mStyledContext);
// [...]
this.onCreatePreferences(savedInstanceState, rootKey);
}
}
The important lines:
this.getActivity().getTheme().resolveAttribute(attr.preferenceTheme, tv, true);
int theme = tv.resourceId;
Here the preferenceTheme
is being retrieved from the Activity's theme. If it exists (i.e. theme
is not 0), PFC (PreferenceFragmentCompat
) creates a new theme wrapper which will contain the styling infos:
this.mStyledContext = new ContextThemeWrapper(this.getActivity(), theme);
Using this styled context, the PFC can now create the PreferenceManager
:
this.mPreferenceManager = new PreferenceManager(this.mStyledContext);
This PFC's root style is now the preferenceTheme
which contains all the different sub-styles (preferenceStyle
for example).
The problem with your solution is that the Preference
class is looking for a preferenceStyle
attribute in the contructor-passed context. However, it's only defined in your preferenceTheme
, not in the Activity's theme.
Related Topics
How to Free a Component in Android/Ios
Update an Android App (Without Google Play Store Visit)
Android.View.Inflateexception: Binary Xml File: Error Inflating Class Fragment
Android Toast Message Is Not Showing
Disable/Check for Mock Location (Prevent Gps Spoofing)
Displaying Emoticons in Android
How to Create a Simple Divider in the New Navigationview
Installation Error: Install_Parse_Failed_Manifest_Malformed
Draw Overlay in Android (System Wide)
How to Download the Android Sdk Without Downloading Android Studio
How to Add a Library (Android-Support-V7-Appcompat) in Intellij Idea
How to Add Onclick Listener to Recycler View
Android Webview with an Embedded Youtube Video, Full Screen Button Freezes Video
Edittext, Clear Focus on Touch Outside
Css3 Linear-Gradient Not Working on Android