I'm making an app that has some settings, and I want to use the built in PreferenceActivity or PreferenceFragment for the job
Some of the preferences have a long title which I cannot shorten, plus I think that if I ever localize the app (translate to multiple languages) I would face the same problem (for example in German, which has quite long words, sometimes).
What you get in this situation is just the beginning of the text and then "..." (or less dots, which doesn't make much sense btw) in the end of it.
Example:
I know that the PreferenceActivity extends from ListActivity, so I can change its adapter to whatever I wish, but that would remove the way it works.
I also know that I can extend from each of the types of the preferences classes, use the "onCreateView" method to have a reference to the created view and then access its children, but this is weird, no? I mean, it's almost like assuming that it will never change the way it looks.
EDIT: Here's a sample code of what I've tried:
Extend from each of the preferences classes, and in each of them , use:
...
@Override
protected View onCreateView(final ViewGroup parent)
{
final View view=super.onCreateView(parent);
ViewUtil.handlePreferenceTitleTextView(view);
return view;
}
...
//ViewUtil.java :
private void handlePreferenceTitleTextView(final View v)
{
final TextView titleTextView=(TextView)v.findViewById(android.R.id.title);
if(titleTextView!=null)
titleTextView.setSingleLine(false);
}
It works, but I don't think it's recommended as Google might change the way preferences views work.
How to handle long text in preferences' titles on Android ?
Is it possible to make it have an ellipsize / marquee (so that it will have an animation to show everything) ? Or maybe auto fit the font size? Or set it to have word wrap ? Or a horizontal scrollView that will allow the user to scroll to read the rest of the text?
Is there maybe a convention of how to handle such cases? Maybe long clicking to show a toast/dialog for seeing the whole text?
app:singleLineTitle="false"
<Preference
app:key="your_key"
app:singleLineTitle="false"
app:title="LONG TITLEEEEEEE EEEEEEEEE EEEEEEEEEEEEEEE" />
Works for Switches etc too
This is my solution of the problem for specific case of the SwitchPreference
and for a preference in general.
First of all, I should note that for API levels before 14 it looks like preference titles were multiline by default - at least I did not see any problems with long titles in Android 2.3.3. In newer versions of Android this behaviour has changed to forced single line title.
The workaround is to tweek the SwitchPreference
or any other type of preference's layout a bit.
In the preference screen file add the android:layout
attribute for required preference, for example:
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory android:title="@string/prefs_category">
<SwitchPreference
android:key="keyOfThePreference"
android:title="@string/pref_title"
android:switchTextOn="@string/pref_on"
android:switchTextOff="@string/pref_off"
android:summaryOn="@string/pref_enabled"
android:summaryOff="@string/pref_disabled"
android:layout="@layout/preference_multiline"
/>
...
Next, provide the preference_multiline.xml
with alternative layout. I used a modified version of the standard preference.xml
:
<?xml version="1.0" encoding="utf-8"?>
<!-- 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="false"
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>
Here I deliberately changed android:singleLine
value in the title's TextView
from true
to false
. This does the job.
Based on solution from here and here , this is a way to set it for all, if anyone wishes:
abstract class BasePreferenceFragment : PreferenceFragmentCompat() {
private fun applyOperationsForAllPreferences(preference: Preference) {
// preference.isIconSpaceReserved = false //you can add this too, if you don't want icons space
preference.isSingleLineTitle = false
if (preference is PreferenceGroup)
for (i in 0 until preference.preferenceCount)
applyOperationsForAllPreferences(preference.getPreference(i))
}
override fun setPreferenceScreen(preferenceScreen: PreferenceScreen?) {
preferenceScreen?.let { applyOperationsForAllPreferences(it) }
super.setPreferenceScreen(preferenceScreen)
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With