7

Please don't point me to How to wrap preference title? as it doesn't work for the case where (as I commented) you use a @strings/ reference to a strings.xml file.

If you use

android:title="@string/some_string"

and put

<string name="some_string">the string I want \n to wrap</string>

into strings.xml, the \n is ignored.

Community
  • 1
  • 1
dentex
  • 3,223
  • 4
  • 28
  • 47
  • look [here][1] , you should use a line break [1]: http://stackoverflow.com/questions/5460256/string-resource-new-line-n-not-possible – Roman Blachman Oct 27 '13 at 09:00
  • 1
    @Roman Blachman: thanks, but the line break `\n` it's exactly what is not working. – dentex Oct 27 '13 at 10:08

3 Answers3

4

For most Android versions, there is no exposed API to allow line wrapping on Preference titles. This leads to the unfortunate common bug of truncated/faded text on medium-to-long titles, especially on small screen devices in portrait orientation:

&ltPreferenceScreen
    android:key="my_pref_key"
    android:title="A Long Preference Title that should wrap to multiple lines" />

Before - Single-line preference titles, in Holo and Material Theme

But there are 2 ways to workaround it:

1. The easy way - But this only works on Android 8 (API 26) and above:

Use android:singleLineTitle="false" like this:

&ltPreferenceScreen
    android:key="my_pref_key"
    android:title="A Long Preference Title that should wrap to multiple lines"
    android:singleLineTitle="false" />

2. The hard way - Custom Preference Child layouts - This works on all Android versions:

For Preferences that have long titles, use a custom layout on them (like this), where the TextView has explicitly turned off single-line text. But you have to set the layouts programmatically, because the themes are different between Android 4 (Holo theme) and Android 5 and above (Material theme).

SettingsFragment.java or SettingsActivity.java:

PreferenceScreen myPreferenceItem = (PreferenceScreen)
    getPreferenceScreen().findPreference("my_pref_key");

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    myPreferenceItem.
        setLayoutResource(R.layout.preference_child_material_customized);
} else {
    myPreferenceItem.
        setLayoutResource(R.layout.preference_child_holo_customized);
}

After - Multi-line preference titles, in Holo and Material Theme

Example for res/layout/preference_child_material_customized.xml:

Copy this file from your Android SDK/platforms/android-22/data/res/layout/ preference_child_material.xml (like this one) and customize it:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginStart="?android:attr/listPreferredItemPaddingStart"
    android:minHeight="?android:attr/listPreferredItemHeight"
    android:gravity="center_vertical"
    android:paddingStart="?android:attr/listPreferredItemPaddingStart"
    android:paddingEnd="?android:attr/listPreferredItemPaddingEnd">

    <LinearLayout
        android:id="@+android:id/icon_frame"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:minWidth="40dip"
        android:gravity="start|center_vertical"
        android:orientation="horizontal">
        <ImageView
            android:id="@+android:id/icon"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginEnd="8dip" />
    </LinearLayout>

    <RelativeLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:paddingTop="16dip"
        android:paddingBottom="16dip">

        <TextView android:id="@+android:id/title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:singleLine="false"
            android:textAppearance="?android:attr/textAppearanceListItem" />

        <TextView android:id="@+android:id/summary"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@android:id/title"
            android:layout_alignStart="@android:id/title"
            android:textAppearance="?android:attr/textAppearanceListItemSecondary"
            android:textColor="?android:attr/textColorSecondary"
            android:maxLines="10" />

    </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:minWidth="58dip"
        android:gravity="end|center_vertical"
        android:orientation="vertical" />

</LinearLayout>

Notice the line android:singleLine="false" on the TextView.

For res/layout/preference_child_holo_customized.xml, you should copy it from your Android SDK/platforms/android-19/data/res/layout/ preference_child.xml or preference_child_holo.xml (like this one) and customize it in a similar way.

Mr-IDE
  • 7,051
  • 1
  • 53
  • 59
  • It requires API 26 - not API 27. – Dmitry Sep 15 '18 at 19:58
  • 1
    Unfortunately, it doesn't work with `CheckBoxPreference`. – Dmitry Sep 15 '18 at 20:03
  • @Dmitry I corrected it to API 26, thanks. I don't know how to fix it for CheckBoxPreference. – Mr-IDE Sep 16 '18 at 09:41
  • @galaxigirl I believe it does work with `ListPreference`. On Android 8 and above, you should use `android:singleLineTitle="false"`. On Android 7 and below, you must use a custom layout, like `android:layout="@layout/preference_child_material_without_icon"` -- This is a similar layout to `preference_child_material_customized.xml`, but you should remove the LinearLayout block that contains the icon. – Mr-IDE Mar 18 '20 at 18:20
  • @Mr-IDE I tested it on API 28 - regular Preference is wrapped, ListPreference is ellipsized – galaxigirl Mar 19 '20 at 10:46
  • @galaxigirl I don't understand why it doesn't work for you. I have attached an image here to show what I get: https://i.stack.imgur.com/TO9tJ.png -- Maybe it can help. I tested it on `android.preference.Preference` and `androidx.preference.Preference`. – Mr-IDE Mar 19 '20 at 18:09
  • @Mr-IDE I believe it works for you because of the customized layout. Does it work for you on API 26+ without it? – galaxigirl Mar 23 '20 at 11:10
2

You can use app:singleLineTitle="false" with androidx.preference:preference, e.g.:

<SwitchPreferenceCompat
        app:defaultValue="false"
        app:iconSpaceReserved="false"
        app:key="important_switch"
        app:singleLineTitle="false"
        app:title="@string/pref_switch_title" />
mklkj
  • 300
  • 4
  • 8
  • For me, `singleLineTitle` took effect when I used `SwitchPreference`, but not when I used `SwitchPreferenceCompat`. – rmtheis Oct 14 '21 at 16:21
1

I think all titles inside preference screen are expected to be single line.
I don't think declaring as android:title="The title of this preference\nis this." will work. This will also ignore \n.

So, my suggestion is, make title single line and make a summary to describe it.

<CheckBoxPreference android:key="extention"
    android:title="@string/title"
    android:summary="@string/summary"
    android:defaultValue="true"
    />

Note: \n will work for summary

Nizam
  • 5,698
  • 9
  • 45
  • 57
  • Indeed, it doesn't work also for a string with no `@string/...` reference. I needed this to always put an `(experimental)` wrapped at the end of the title. It will do its job also at the end of the (already present) summary. Thanks. – dentex Oct 27 '13 at 10:14
  • 1
    But in the summary I want to show the selected value by %s. Is there in the xml to show in the summary %s concatenated with a string(@string/summary)? – Code Pope Mar 28 '17 at 23:57
  • This may not be the accepted answer. Your solution preclude the real purpose of `android:summary`. There is an actual solution for achieve that? – user2342558 Jun 25 '19 at 13:27