21

I want to change the text color in android preferences fragment. I am currently using a custom theme to change the checkbox image, background, onClick highlighting and it all works great...besides the text color. I don't want to use a default theme, I want to have my own theme so it all looks how I want to but just change the text color, can someone please help.

styles.xml

<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:android="http://schemas.android.com/apk/res/android">
    <style name="selectedTextStyle">  
        <item name="android:textSize">18sp</item>
    </style>
    <style name="buttonTextStyle">  
        <item name="android:textSize">20sp</item>
    </style>
    <style name="PreferencesTheme" >
        <item name="android:windowBackground">@drawable/lists_background</item>
        <item name="android:listViewStyle">@style/listViewPrefs</item>
        <item name="android:checkboxStyle">@style/MyCheckbox</item>

    </style>
    <style name="MyTextAppearance" parent="@android:style/TextAppearance">
        <item name="android:textColor">@color/black</item>
      </style>
    <style name="listViewPrefs" parent="@android:Widget.ListView">
        <item name="android:listSelector">@layout/list_selector_master</item>
        <item name="android:textAppearance">@style/MyTextAppearance</item>
    </style>
    <style name="MyCheckbox" parent="android:Widget.CompoundButton.CheckBox">
        <item name="android:button">@drawable/btn_check</item>
    </style>

</resources>

Manifest:

        <activity
            android:name="com.package.SettingsActivity"
            android:theme="@style/PreferencesTheme"
            android:configChanges="keyboard|orientation" >
        </activity>

Activity:

import android.app.Activity;
import android.os.Bundle;
import android.preference.PreferenceFragment;

public class SettingsActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // Display the fragment as the main content.
        getFragmentManager().beginTransaction()
                .replace(android.R.id.content, new SettingsFragment())
                .commit();

    }
    public static class SettingsFragment extends PreferenceFragment {
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);

            // Load the preferences from an XML resource
            addPreferencesFromResource(R.xml.preferences);

        }
    }

}
AlexIIP
  • 2,461
  • 5
  • 29
  • 44

8 Answers8

13

Here are the two TextView objects from preference.xml (layout for a Preference):

    <TextView android:id="@+android:id/title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:singleLine="true"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:ellipsize="marquee"
        android:fadingEdge="horizontal" />

    <TextView android:id="@+android:id/summary"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@android:id/title"
        android:layout_alignLeft="@android:id/title"
        android:textAppearance="?android:attr/textAppearanceSmall"
        android:textColor="?android:attr/textColorSecondary"
        android:maxLines="4" />

So looks like you can override textAppearanceLarge and textColorSecondary in your theme to achieve a color change. Here's an example:

<style name="AppTheme">
    <item name="android:textAppearanceLarge">@style/MyTextAppearance</item>
    <item name="android:checkboxStyle">@style/MyCheckBox</item>
</style>

<style name="MyCheckBox" parent="@android:style/Widget.CompoundButton.CheckBox">
    <item name="android:button">@android:drawable/btn_star</item>
</style>

<style name="MyTextAppearance" parent="@android:style/TextAppearance.Large">
    <item name="android:textColor">#ff0000</item>
</style>
Jason Robinson
  • 31,005
  • 19
  • 77
  • 131
  • I think that is it. Could you please help me do so, `@style/MyTextAppearance` did not seem to do the trick. – AlexIIP Feb 01 '13 at 07:09
  • @AlexIIP You placed it in the `PreferenceTheme` style? – Jason Robinson Feb 01 '13 at 07:15
  • Yes I did, the above line is from the PreferenceTheme and as you can see `MyTextAppearance` has `textColor`. Should I change it to something else? – AlexIIP Feb 01 '13 at 07:18
  • @AlexIIP Isn't the color black by default? Try a different color. – Jason Robinson Feb 01 '13 at 07:19
  • No the color is light gray and it clashes with my background, I can barely see the text. – AlexIIP Feb 01 '13 at 07:21
  • @AlexIIP Check my edit. I just created a new application to test this out and it worked for me. – Jason Robinson Feb 01 '13 at 07:35
  • First of all thank you! Second, I am trying to reproduce it and I can't. If i set `PreferenceTheme` to `android:Theme.Light` this changes text to black but then it gets rid of my custom checkbox and list view selector. If I don't set parent theme to light then nothing happens. (I believe the default color for Theme Light is black). – AlexIIP Feb 01 '13 at 07:40
  • Try setting the parent theme to `android:Theme.Black` – Jason Robinson Feb 01 '13 at 07:45
  • Ok, so again, this does change the color of my text but it makes my action bar look old and overrides my listView selector colors. It goes to default ugly yellow selector. – AlexIIP Feb 01 '13 at 07:46
  • This is a bit difficult because you originally didn't define a parent theme for your custom theme, so I'm not sure where it's inheriting its values from. Without knowing that, I don't know where to look to find what style needs to be overridden. – Jason Robinson Feb 01 '13 at 07:54
  • Could I select Theme.Light and then override the selector that way and redefine the titlebar to system default? Would you know how to do that? – AlexIIP Feb 01 '13 at 07:57
  • I removed the parent from my theme and everything still works fine. I even changed the default check box the exact same way you did. So that should be working. I'll edit my answer again with how my theme looks now. – Jason Robinson Feb 01 '13 at 08:03
  • I still can't get it to work. I removed the background to try it and still nothing. I am updating my original with my SettingsActivity which uses a PreferenceFragment, could that be the issue? – AlexIIP Feb 01 '13 at 08:12
  • 2
    It looks fine to me. I'm not sure why it wouldn't work for you but work for me. Not sure what else to suggest. Sorry :( – Jason Robinson Feb 01 '13 at 08:20
  • Thank you so much for your time. If no one else answers Ill give you the answer credits. – AlexIIP Feb 01 '13 at 08:21
  • 1
    I ended up having to redefine `android:textAppearanceMedium` in order to change the text color of the preference title. I have zero understanding as to why this worked and not `android:textAppearanceLarge`. – mharper Oct 19 '13 at 23:35
  • The holo preference layout, [preference_holo.xml](https://github.com/android/platform_frameworks_base/blob/master/core/res/res/layout/preference_holo.xml), uses textAppearance.Medium. – dgmltn Dec 19 '14 at 21:21
10

I think an easy and clear way to do that is next:

res/values/styles.xml

<style name="SettingsFragmentStyle">

    <item name="android:textColorSecondary">#222</item>
    <item name="android:textColor">#CCC</item>
    <item name="android:background">#999</item>
    ...
</style>

In the Activity that contains PreferenceFragment subclass inside onCreate:

setTheme(R.style.SettingsFragmentStyle);
Andrew
  • 36,676
  • 11
  • 141
  • 113
  • 1
    For me it was the `textColorSecondary` (and `textColorPrimary`) that made it work. Thanks for sharing! – dustinrwh Dec 15 '16 at 18:13
6

Just found an answer that gets the job done.

This file is default layout for the preference list item:

<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2006 The Android Open Source Project

     Licensed under the Apache License, Version 2.0 (the "License");
     you may not use this file except in compliance with the License.
     You may obtain a copy of the License at

          http://www.apache.org/licenses/LICENSE-2.0

     Unless required by applicable law or agreed to in writing, software
     distributed under the License is distributed on an "AS IS" BASIS,
     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     See the License for the specific language governing permissions and
     limitations under the License.
-->

<!-- Layout for a Preference in a PreferenceActivity. The
     Preference is able to place a specific widget for its particular
     type in the "widget_frame" layout. -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:minHeight="?android:attr/listPreferredItemHeight"
    android:gravity="center_vertical"
    android:paddingRight="?android:attr/scrollbarSize"
    android:background="?android:attr/selectableItemBackground" >

    <ImageView
        android:id="@+android:id/icon"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        />

    <RelativeLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="15dip"
        android:layout_marginRight="6dip"
        android:layout_marginTop="6dip"
        android:layout_marginBottom="6dip"
        android:layout_weight="1">

        <TextView android:id="@+android:id/title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:singleLine="true"
            android:textAppearance="?android:attr/textAppearanceLarge"
            android:ellipsize="marquee"
            android:fadingEdge="horizontal" />

        <TextView android:id="@+android:id/summary"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@android:id/title"
            android:layout_alignLeft="@android:id/title"
            android:textAppearance="?android:attr/textAppearanceSmall"
            android:textColor="?android:attr/textColorSecondary"
            android:maxLines="4" />

    </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="center_vertical"
        android:orientation="vertical" />

</LinearLayout>

You can use it as base and create your own custom layout. This layout must be applied within each Preference like this

<Preference android:key="somekey" 
android:title="Title" 
android:summary="Summary" 
android:layout="@layout/custom_preference_layout"/>

You can change the whole layout outside the list, you just need to have a layout file that contains a listview where the preferences will be populated like this:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Something" />

    <ListView
        android:id="@android:id/list"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" />

</LinearLayout>

To override the default layout for the PreferenceFragment, override the method onCreateView and change the inflated view:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    return inflater.inflate(R.layout.custom_options_layout, null);
}

Based off these answers:

Creating a custom layout for preferences

How to add a button to PreferenceScreen

Android: How to adjust Margin/Padding in Preference?

Community
  • 1
  • 1
Saito Mea
  • 455
  • 4
  • 11
  • Since I can't mark my own answer as correct for the bounty I'm still accepting answers that achieve the same using only themes (what seems to be what the original poster wanted). – Saito Mea Jul 17 '13 at 22:48
2

To me nothing of the above methods didn't work. I ended up extending Prefernces class of the kind I used, in my case CheckBoxPrefernces:

 public class MyPreferenceCheckBox extends CheckBoxPreference {

    public MyPreferenceCheckBox(Context context) {
        super(context);
    }
    public MyPreferenceCheckBox(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
    public MyPreferenceCheckBox(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    protected View onCreateView(ViewGroup parent) {
        ViewGroup root = (ViewGroup) super.onCreateView(parent);
        ((TextView)root.findViewById(android.R.id.title)).setTextColor(parent.getResources().getColor(R.color.red));
        ((TextView)root.findViewById(android.R.id.summary)).setTextColor(parent.getResources().getColor(R.color.red));
        return root;
    }
}

And the use in the prefs.xml:

 <com.my.package.name.MyPreferenceCheckBox
        android:title="@string/my_title"
        android:defaultValue="true"
        android:key="@string/my_key"
        android:summary="On/Off" />

This answer showed me that path:

Community
  • 1
  • 1
yshahak
  • 4,996
  • 1
  • 31
  • 37
1

Haven't got enough rep to comment or upvote, but I just wanted to add that mharper's suggestion about TextAppearanceMedium also worked for me in regards to changing the text colour. If somebody knows why this is, please do explain it.

So just adjust the accepted answer like so:

<style name="AppTheme">
     <item name="android:textAppearanceMedium">@style/MyTextAppearance</item>
</style>

<style name="MyTextAppearance" parent="@android:style/TextAppearance.Medium">
     <item name="android:textColor">#ff0000</item>
</style>

At least if nobody can explain why this is, it might stop somebody having the same difficulty I did trying to change the text colour.

Woodstown
  • 26
  • 5
  • Your preferences are probably using [preference_holo.xml](https://github.com/android/platform_frameworks_base/blob/master/core/res/res/layout/preference_holo.xml), not [preference.xml](https://github.com/android/platform_frameworks_base/blob/master/core/res/res/layout/preference.xml). The holo version uses textAppearance.Medium. – dgmltn Dec 19 '14 at 21:18
1

I was able to change text color in PreferenceFragment with this:

styles.xml

<resources>

    <style name="SettingsTheme" parent="android:Theme.Holo">
        <item name="android:textColorPrimary">@color/light_blue_font_color</item>
        <item name="android:textColorSecondary">@color/white_font_color</item>
        <item name="android:textColorTertiary">@color/white_font_color</item>
    </style>

</resources>

colors.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="light_blue_font_color">#33b5e5 </color>
    <color name="white_font_color">#ffffff </color>
</resources>

AndroidManifest.xml

<activity
    android:name="xx.yy.zz.SettingsActivity"
    android:theme="@style/SettingsTheme" >
</activity>
0

If you're using compat library, just add:

<item name="colorAccent">#ff0000</item>

to your style

Oded Breiner
  • 28,523
  • 10
  • 105
  • 71
-1

I work with min API 11 and compile whith 23. set theme and after set background for this theme. if you work with > API 14 you can use Theme_DeviceDefault.

This is the simplest solution I find :

public static class SettingsFragment extends PreferenceFragment {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        getActivity().setTheme(android.R.style.Theme_Holo);
        // Load the preferences from an XML resource
        addPreferencesFromResource(R.xml.settings);
    }

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        if(view != null){
            view.setBackgroundColor(ContextCompat.getColor(getActivity(), android.R.color.background_dark));
        }
    }
}
Sinelc
  • 104
  • 1
  • 4
  • Careful with this, is just reset the entire theme on the activity. Meaning when you display another fragment it will have this same theme. – lostintranslation Jan 26 '17 at 20:23