How to wrap a preference title? (Really)
Asked Answered
D

3

8

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.

Disperse answered 27/10, 2013 at 8:53 Comment(2)
look [here][1] , you should use a line break [1]: #5460756Mendacious
@Roman Blachman: thanks, but the line break \n it's exactly what is not working.Disperse
H
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:

<PreferenceScreen
    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:

<PreferenceScreen
    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.

Himelman answered 3/8, 2018 at 20:54 Comment(7)
It requires API 26 - not API 27.Recidivism
Unfortunately, it doesn't work with CheckBoxPreference.Recidivism
@Recidivism I corrected it to API 26, thanks. I don't know how to fix it for CheckBoxPreference.Himelman
@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.Himelman
@Himelman I tested it on API 28 - regular Preference is wrapped, ListPreference is ellipsizedIndraft
@Indraft I don't understand why it doesn't work for you. I have attached an image here to show what I get: i.sstatic.net/TO9tJ.png -- Maybe it can help. I tested it on android.preference.Preference and androidx.preference.Preference.Himelman
@Himelman I believe it works for you because of the customized layout. Does it work for you on API 26+ without it?Indraft
N
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" />
Niacin answered 24/5, 2020 at 17:21 Comment(1)
For me, singleLineTitle took effect when I used SwitchPreference, but not when I used SwitchPreferenceCompat.Chic
K
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

Krishna answered 27/10, 2013 at 9:35 Comment(3)
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.Disperse
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)?Intensive
This may not be the accepted answer. Your solution preclude the real purpose of android:summary. There is an actual solution for achieve that?Konstance

© 2022 - 2024 — McMap. All rights reserved.