Настройка макета PreferenceScreen
Мои требования
Примечание: мне нужно поддерживать Android API 15 и выше.
В моем PreferenceFragment я динамически добавляю PreferenceScreen's в PreferenceCategory.
PreferenceScreen as = mgr.createPreferenceScreen(context);
as.setTitle(name);
myCategory.addPreference(as);
Когда настройки Activity рендерится, эти PreferenceScreens отображаются только с заголовком в строке, см. Изображение ниже.
Я хочу настроить то, что показано в этом ряду. В идеале я хотел бы иметь заголовок со сводкой ниже, значок слева от заголовка / резюме и в некоторых строках значок справа. Смотрите изображение макета ниже.
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"/>
это будет производить интерфейс, как показано ниже
Это приближает меня к тому, что я хотел бы, но все еще не совсем то, что я хотел бы (пропуская значок в начале строки).
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;
}
});