Настройка макета PreferenceScreen

Мои требования

Примечание: мне нужно поддерживать Android API 15 и выше.

В моем PreferenceFragment я динамически добавляю PreferenceScreen's в PreferenceCategory.

PreferenceScreen as = mgr.createPreferenceScreen(context);
as.setTitle(name); 
myCategory.addPreference(as);

Когда настройки Activity рендерится, эти PreferenceScreens отображаются только с заголовком в строке, см. Изображение ниже.PreferenceScreen, показанный в деятельности настройки

Я хочу настроить то, что показано в этом ряду. В идеале я хотел бы иметь заголовок со сводкой ниже, значок слева от заголовка / резюме и в некоторых строках значок справа. Смотрите изображение макета ниже.

Желаемое отображение моего экрана настроек

PreferenceScreen.setWidgetLayoutResource (int widgetLayoutResId)

Я знаю, что могу использовать "setWidgetLayoutResource", чтобы добавить значок справа от макета строки (и сводку с "setSummary"), используя следующий код в моей деятельности по настройке

PreferenceScreen as = mgr.createPreferenceScreen(context);
as.setTitle(name); 
as.setSummary(summary);
as.setWidgetLayoutResource(R.layout.as_widget);
myCategory.addPreference(as);

где as_widget.xml

<?xml version="1.0" encoding="utf-8"?>
<ImageView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:src="@drawable/ic_action_favorite"/>

это будет производить интерфейс, как показано нижеМакет с использованием setWidgetLayoutResource

Это приближает меня к тому, что я хотел бы, но все еще не совсем то, что я хотел бы (пропуская значок в начале строки).

PreferenceScreen.setLayoutResource (int layoutResId)

Я верю, что если я буду использовать это, то смогу контролировать рендеринг всего ряда. Я видел примеры этого на stackru, такие как

Насколько я понимаю, указанный файл макета должен иметь следующее

  • его корневой вид с идентификатором "@android:id/widget_frame"
  • представление с идентификатором android:id="@+android:id/title" (это место, где находится строка, указанная в PreferenceScreen.setTitle)
  • представление с идентификатором android:id="@+android:id/summary" (это место, где находится строка, указанная в PreferenceScreen.setSummary)

Однако, когда я пытаюсь это сделать, Android Studio выделяет "@ + android: id / summary" с ошибкой "Не удается разрешить символ" @ + android: id / summary ". При запуске приложения мои строки отображаются полностью пустыми.

Моя ява

PreferenceScreen as = mgr.createPreferenceScreen(context);
as.setTitle(name); 
as.setSummary(summary);
as.setLayoutResource(R.layout.as_row_layout);
myCategory.addPreference(as);

И мой макет

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@android:id/widget_frame"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:minHeight="?android:attr/listPreferredItemHeight"
    android:gravity="center_vertical"
    android:paddingRight="?android:attr/scrollbarSize">

    <ImageView
        android:id="@+id/icon1"
        android:src="@drawable/ic_action_email"
        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>

    <ImageView
        android:id="@+id/icon2"
        android:src="@drawable/ic_action_favorite"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center" />
</LinearLayout>

Расширение PreferenceScreen

Я посмотрел на расширенный PreferenceScreen, чтобы переписать способ его рендеринга, но, похоже, этот класс теперь сделан окончательным, поэтому все примеры в Интернете, которые делают это таким образом, не могут быть использованы.

2 ответа

Решение

Мне удалось заставить это работать.

Preference класс использует com.android.internal.R.layout.preference как его макет. Это содержит ImageView для значка на левой стороне, затем заголовок и сводные текстовые представления и, наконец, widget_frame Макет на правой стороне.

По телефонуPreferenceScreen.setIcon(..)"Вы можете установить рисование для размещения в виде значка изображения. PreferenceScreen.setWidgetLayoutResource("...") Вы можете установить макет для размещения в widget_frame макет, в моем случае я поместил макет ImageView, содержащий мое изображение.

Вот мой код Java.

PreferenceScreen as = mgr.createPreferenceScreen(context);
as.setTitle(name);
as.setSummary(summary);

// add an icon to the PreferenceScreen, 
// this is rendered on the left hand side of the row
accountScreen.setIcon(R.drawable.my_pref_icon);

// specify the layout to inflate into the widget area on the 
// right hand side of the row, this layout is just my image
as.setWidgetLayoutResource(R.layout.as_widget);

myCategory.addPreference(as);

Это создает макет, подобный следующемузначки без выравнивания

Проблема с этим макетом заключается в том, что значки не выровнены по левому краю с текстом настроек, которые не имеют значков.

Это можно решить, указав макет для PreferenceScreen также. Я скопировал Android preference.xml в мой проект (переименовывая его соответственно для моего сценария использования), и я изменил ImageView, чтобы иметь отступ слева и поле 0dp.

От

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

в

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

Затем я указал свою копию preference.xml для макета PreferenceScreen. Так что моя ява сейчас

PreferenceScreen as = mgr.createPreferenceScreen(context);
as.setTitle(name);
as.setSummary(summary);

// add an icon to the PreferenceScreen, 
// this is rendered on the left hand side of the row
accountScreen.setIcon(R.drawable.my_pref_icon);

// specify the layout to inflate into the widget area on the 
// right hand side of the row, this layout is just my image
as.setWidgetLayoutResource(R.layout.as_widget);

// specify the layout for the preference screen row when it is
// rendered as a row in a preference activity/fragment
as.setLayoutResource(R.layout.preference_row_layout);

myCategory.addPreference(as);

Я считаю, что причина моей первоначальной попытки использования PreferenceScreen.setLayoutResource не работал, потому что указанная мной схема была неправильной. Неправильный макет имел весь макет с идентификатором @android:id/widget_frameт.е.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@android:id/widget_frame" ...>
    .....
</LinearLayout>

Правильный макет не требует идентификатора для основного макета, но должен содержать дочерние представления с идентификаторами @+android:id/icon, @+android:id/title, @+android:id/summary, @+android:id/widget_frameт.е.

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

    <ImageView android:id="@+android:id/icon" ....>
     ....
    <TextView android:id="@+android:id/title" ...>
     ....
    <TextView android:id="@+android:id/summary" ...>
    ....
    <LinearLayout android:id="@+android:id/widget_frame" ..>
    ....
</LinearLayout>

Вы также можете настроить макет предпочтения путем переопределения Preference.onCreateView(parent), В приведенном ниже примере используется анонимный внутренний класс для создания красных настроек.

    screen.addPreference(
        new Preference(context) {
            @Override
            protected View onCreateView(ViewGroup parent) {
                View view = super.onCreateView(parent);
                view.setBackgroundColor(Color.RED);
                return view;
            }
        });
Другие вопросы по тегам