androidandroid-fragmentsandroid-themepreferencefragmentcompat

Theming PreferenceFragmentCompat


I'm having some troubles setting a theme to PreferenceFragmentCompat trying to achieve this:

enter image description here

I have these styles set:

<style name="AppThemeBase" parent="Theme.MaterialComponents.Light.NoActionBar">
    <!-- Customize your theme here. -->
    <item name="colorPrimary">@color/colorPrimary</item>
    <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
    <item name="colorAccent">@color/colorAccent</item>

    <item name="android:windowLightStatusBar">true</item>
    <item name="android:statusBarColor">@color/status_bar</item>

    <item name="colorControlNormal">@color/colorPrimary</item>
    <item name="preferenceTheme">@style/AppThemeBase.RecordingPreferencesTheme</item>
</style>

<style name="AppThemeBase.RecordingPreferencesTheme" parent="@style/PreferenceThemeOverlay">
    <item name="android:textColorPrimary">#FD0000</item>
    <item name="android:textColorSecondary">#1F6F2B</item>
</style>

With this options I can see what I want to achieve in Android Studio layout preview but when it does not have effect when I execute it

The result when I execute:

enter image description here

The only thing it worked so far is using <item name="android:textColor">#FD0000</item> that will change the tittle colour but I can't find a way to change the summary colour.

Another question I have is if there is a way to set the theme just for that preference fragment instead of using it in all preferences fragments. Using android:theme at the root of the fragment layout isn't working for me :(

Update:

As per @Susan question this is how I try to use android:theme at the root of the fragment layout I've created this theme based in the main one

<style name="RecordingPreferenceTheme" parent="AppThemeBase">
    <item name="preferenceTheme">@style/AppThemeBase.RecordingPreferencesTheme</item>
</style>

And this is the preference layout where I have a fragment which will inflate the PreferenceFragmentCompat

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:theme="@style/RecordingPreferenceTheme">

<include
    android:id="@+id/include"
    layout="@layout/toolbar"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintHorizontal_bias="0.5"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent" />

<fragment
    android:id="@+id/fragment_container_settings"
    android:name="com.example.app.RecordSettingsFragment$RecordPreferences"
    android:layout_width="0dp"
    android:layout_height="0dp"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toBottomOf="@+id/include" />

</androidx.constraintlayout.widget.ConstraintLayout>

And at the root of the layout I'll set android:theme="@style/RecordingPreferenceTheme" but it doesn't work, just changes in the main theme set in Activity will have some effect. I've already tried customize PreferenceFragmentCompat layout with same results.

Cheers!!


Solution

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