自定义PreferenceScreen的布局 [英] Customizing the layout of a PreferenceScreen

查看:125
本文介绍了自定义PreferenceScreen的布局的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的要求

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

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

In my PreferenceFragment I am dynamically adding PreferenceScreen's to a PreferenceCategory.

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

当设置活动"渲染这些PreferenceScreen时,仅在其行中显示了标题,请参见下图.

When the settings Activity renders these PreferenceScreens are rendered with just a title in it's row, see the image below.

我想自定义此行中显示的内容.理想情况下,我希望标题下面带有一个摘要,标题/摘要的左侧是一个图标,而在某些行上,右侧则是一个图标.请参见下面的样机图片.

I want to customize what is shown in this row. Ideally I would like to have a title with a summary below, an icon to the left of the title/summary and on certain rows an icon on the right hand side. See the mockup image below.

PreferenceScreen.setWidgetLayoutResource(int widgetLayoutResId)

PreferenceScreen.setWidgetLayoutResource(int widgetLayoutResId)

我知道我可以在设置活动中使用以下代码,使用"setWidgetLayoutResource"在行布局的右侧添加图标(以及带有"setSummary"的摘要)

I know I can use "setWidgetLayoutResource" to add an icon to the right of the row layout (and a summary with "setSummary") using the following code in my settings activity

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

"as_widget.xml"所在的位置

where "as_widget.xml" is

<?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"/>

这将产生如下的UI

this will produce UI like the following

这使我更接近我想要的东西,但仍然不是我想要的东西(在行首缺少该图标).

This gets me closer to what I would like but still not exactly what I would like (missing the icon at the beginning of the row).

PreferenceScreen.setLayoutResource(int layoutResId)

PreferenceScreen.setLayoutResource(int layoutResId)

我相信,如果我使用它,那么我可以控制整个行的呈现.我已经在stackoverflow上看到了这样的示例,例如

I believe if I use this, then I can control the rendering of the whole row. I have seen examples of this on stackoverflow, such as

  • Setting preference layout and changing the attribute in it
  • Creating a custom layout for preferences

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

From my understanding the layout file you specify has to have the following

  • 其ID为"@android:id/widget_frame"的根视图
  • 一个ID为android:id ="@ + android:id/title"的视图(这是 放置在PreferenceScreen.setTitle中指定的字符串)
  • 一个ID为android:id ="@ + android:id/summary"的视图(在此处 放置在PreferenceScreen.setSummary中指定的字符串)
  • its root View with the id "@android:id/widget_frame"
  • a view with the id android:id="@+android:id/title" (this is where the string specified in PreferenceScreen.setTitle is placed)
  • a view with the id android:id="@+android:id/summary" (this is where the string specified in PreferenceScreen.setSummary is placed)

但是,当我尝试执行此操作时,Android Studio突出显示"@ + android:id/summary",错误为无法解析符号'@ + android:id/summary'.当应用程序运行时,我的行会完全呈现空白.

However when I try and do this, Android Studio highlights "@+android:id/summary" with the error "Can not resolve symbol '@+android:id/summary'. When the application runs my rows are rendered completely blank.

我的Java是

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来覆盖它的呈现方式,但看来该类现在已经定型了,因此无法使用Internet上以这种方式进行操作的所有示例.

I looked at extended PreferenceScreen to overwrite how it renders, but it appears this class has now been made final so all examples on the internet that do it that way can not be used.

推荐答案

我设法使它正常工作.

Preference类使用com.android.internal.R.layout.preference作为其布局.它在左侧包含一个ImageView图标,然后在标题和摘要文本视图中包含一个图标,最后在右侧包含一个widget_frame布局.

The Preference class uses com.android.internal.R.layout.preference as its layout. This contains an ImageView for an icon on the left hand side, then the title and summary textviews and finally a widget_frame Layout on the right hand side.

通过调用"PreferenceScreen.setIcon(..)",可以将可绘制对象设置为放置在图标图像视图中.通过调用PreferenceScreen.setWidgetLayoutResource("..."),您可以将布局设置为放置在widget_frame布局中,在我的情况下,我将放置一个包含图像的ImageView布局.

By calling "PreferenceScreen.setIcon(..)" you can set the drawable to place in the icon image view. By calling PreferenceScreen.setWidgetLayoutResource("...") you can set the layout to place in the widget_frame layout, in my case I put an ImageView layout containing my image.

这是我的Java代码.

Here is my Java code.

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);

这将产生如下所示的布局

This produces a layout like the following

这种布局的问题是图标未与下面没有图标的首选项文本对齐.

The problem with this layout is that the icons do not left align with the text of the preferences below which have no icons.

这也可以通过指定PreferenceScreen的布局来解决.我将Android的preference.xml复制到了我的项目中(针对我的用例对其进行了适当的命名),然后更改了ImageView的左侧填充和空白值为0dp.

This can be resolved by specifying the layout for the PreferenceScreen as well. I copied Android's preference.xml into my project (renaming it appropriately for my usecase) and I changing the ImageView to have a left padding and margin of 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"/>

然后我为PreferenceScreen的布局指定了preference.xml的副本.所以我的Java现在是

I then specified my copy of preference.xml for the PreferenceScreen's layout. So my java is now

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失败的原因是因为我指定的布局不正确.错误的布局具有整个布局,其ID为@android:id/widget_frame,即

I believe the reason my original attempt at using PreferenceScreen.setLayoutResource was not working was because the layout I specified was incorrect. The incorrect layout had the whole layout with an id of @android:id/widget_frame, i.e.

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

正确的布局不需要主布局的ID,但需要包含ID为@+android:id/icon@+android:id/title@+android:id/summary@+android:id/widget_frame子视图,即

The correct layout does not need an id for the main layout, but needs to contain child views with ids of @+android:id/icon, @+android:id/title, @+android:id/summary, @+android:id/widget_frame, i.e.

<?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>

这篇关于自定义PreferenceScreen的布局的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆