自定义PreferenceScreen的布局

se2*_*2as 11 layout android customizing preference preferencescreen

我的要求

注意:我需要支持Android API 15及更高版本.

在我的PreferenceFragment中,我正在将PreferenceScreen动态添加到PreferenceCategory.

PreferenceScreen as = mgr.createPreferenceScreen(context);
as.setTitle(name); 
myCategory.addPreference(as);
Run Code Online (Sandbox Code Playgroud)

当设置活动呈现时,这些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);
Run Code Online (Sandbox Code Playgroud)

其中"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"/>
Run Code Online (Sandbox Code Playgroud)

这将产生如下的UI 使用setWidgetLayoutResource进行布局

这让我更接近我想要的但仍然不完全是我想要的(错过了行开头的图标).

PreferenceScreen.setLayoutResource(int layoutResId)

我相信如果我使用它,那么我可以控制整行的渲染.我在stackoverflow上看过这个例子,比如

根据我的理解,您指定的布局文件必须具有以下内容

  • 它的根视图的id为"@android:id/widget_frame"
  • 一个id为android的视图:id ="@ + android:id/title"(这是放置PreferenceScreen.setTitle中指定的字符串的地方)
  • id为android的视图:id ="@ + android:id/summary"(这是放置PreferenceScreen.setSummary中指定的字符串的位置)

然而,当我尝试这样做时,Android Studio突出显示"@ + android:id/summary",错误为"无法解析符号'@ + android:id/summary'.当应用程序运行时,我的行呈现为完全空白.

我的java是

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

我的布局是

<?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>
Run Code Online (Sandbox Code Playgroud)

扩展PreferenceScreen

我查看了扩展的PreferenceScreen以覆盖它呈现的方式,但看起来这个类现在已经成为最终版,所以互联网上以这种方式执行的所有示例都无法使用.

se2*_*2as 16

我设法让这个工作.

Preference班采用com.android.internal.R.layout.preference作为其布局.这包含左侧图标的ImageView,然后是标题和摘要文本widget_frame视图,最后是右侧的布局.

通过调用" PreferenceScreen.setIcon(..)",您可以将drawable设置为放置在图标图像视图中.通过调用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);
Run Code Online (Sandbox Code Playgroud)

这会产生如下布局 未对齐的图标

此布局的问题在于图标不会与下面没有图标的首选项文本保持对齐.

这可以通过指定其布局来解决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"
    />
Run Code Online (Sandbox Code Playgroud)

<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"/>
Run Code Online (Sandbox Code Playgroud)

然后我指定preference.xml了PreferenceScreen布局的副本.所以我的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);

// 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);
Run Code Online (Sandbox Code Playgroud)

我相信我最初尝试使用的原因PreferenceScreen.setLayoutResource是因为我指定的布局不正确.不正确的布局使整个布局的id为@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>
Run Code Online (Sandbox Code Playgroud)

正确的布局并不需要为主要布局的ID,但需要包含孩子的看法与IDS @+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>
Run Code Online (Sandbox Code Playgroud)