简体   繁体   English

如何在 Android 上的首选项中处理长文本?

[英]How to handle long text in preferences on Android?

Background背景

I'm making an app that has some settings, and I want to use the built in PreferenceActivity or PreferenceFragment for the job我正在制作一个有一些设置的应用程序,我想使用内置的 PreferenceActivity 或 PreferenceFragment 来完成这项工作

The problem问题

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:例子:

在此处输入图片说明

What I've tried我试过的

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.我知道 PreferenceActivity 从 ListActivity 扩展,所以我可以将它的适配器更改为我想要的任何东西,但这会消除它的工作方式。

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?我也知道我可以从首选项类的每种类型进行扩展,使用“onCreateView”方法来引用创建的视图,然后访问它的子视图,但这很奇怪,不是吗? 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.它有效,但我认为不推荐这样做,因为 Google 可能会改变首选项视图的工作方式。

The question问题

How to handle long text in preferences' titles on Android ?如何在 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?也许长按以显示吐司/对话框以查看整个文本?

This is my solution of the problem for specific case of the SwitchPreference and for a preference in general.这是我针对SwitchPreference特定情况和一般偏好的问题的解决方案。

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.首先,我应该注意,对于 14 之前的 API 级别,默认情况下首选项标题似乎是多行的 - 至少我没有看到 Android 2.3.3 中的长标题有任何问题。 In newer versions of Android this behaviour has changed to forced single line title.在较新版本的 Android 中,此行为已更改为强制单行标题。

The workaround is to tweek the SwitchPreference or any other type of preference's layout a bit.解决方法是稍微调整SwitchPreference或任何其他类型的首选项布局。

In the preference screen file add the android:layout attribute for required preference, for example:在首选项屏幕文件中,为所需首选项添加android:layout属性,例如:

<?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.接下来,为preference_multiline.xml提供替代布局。 I used a modified version of the standard preference.xml :我使用了标准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 .在这里,我特意将标题的TextView中的android:singleLine值从true更改为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)
    }

}

2021: When using androidx.preference (likely what everyone has) 2021 年:使用 androidx.preference 时(可能每个人都有)

You can simply use app:singleLineTitle="false"您可以简单地使用app:singleLineTitle="false"

<Preference
        app:key="your_key"
        app:singleLineTitle="false"
        app:title="LONG TITLEEEEEEE EEEEEEEEE EEEEEEEEEEEEEEE" />

Works for Switches etc too也适用于开关等

I didn't want to copy-paste a layout, so I've ended up subclassing the preference:我不想复制粘贴布局,所以我最终将偏好设置为子类:

import android.content.Context;
import android.support.v7.preference.CheckBoxPreference;
import android.support.v7.preference.PreferenceViewHolder;
import android.util.AttributeSet;
import android.widget.TextView;

public class CustomCheckboxPreference extends CheckBoxPreference {

  public CustomCheckboxPreference(Context context) {
    super(context);
  }

  public CustomCheckboxPreference(Context context, AttributeSet attrs) {
    super(context, attrs);
  }

  public CustomCheckboxPreference(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
  }

  public CustomCheckboxPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
    super(context, attrs, defStyleAttr, defStyleRes);
  }

  @Override
  public void onBindViewHolder(PreferenceViewHolder holder) {
    super.onBindViewHolder(holder);
    TextView title = (TextView) holder.findViewById(android.R.id.title);
    if (title != null) {
      title.setSingleLine(false);
    }
  }

}

Then just use it in your prefs.xml :然后只需在您的prefs.xml使用它:

<android.support.v7.preference.PreferenceScreen ...>
  <android.support.v7.preference.PreferenceCategory ...>
    <com.example.CustomCheckboxPreference
      ...
      />

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM