是否可以自定义首选项标题布局? [英] Is it possible to customize preference-header layout?

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

问题描述

我找到了类似的问题,但是找不到最新的特定答案. 我正在使用<preference-header>,按照3.0+设置设计指南(我的目标是4.1.2+)来构建标题.我想为这些标题设置自定义布局.请注意,我不想退回到这里,因为我不支持较早的Android版本.

I have found similar questions, but can't find a specific answer that is up-to-date. I'm using <preference-header>, as per 3.0+ settings design guidelines ( I target 4.1.2+) to build my headers; I want to set a custom layout to these headers. Note that I don't want to fall back to the old PreferenceScreen method as described here, because I don't support older Android version.

据我研究,此布局由PreferenceActivity类的私有成员持有,并使用似乎无法公开访问的可设置样式的属性进行检索:

As far as I could research, this layout is held by a private member of the PreferenceActivity class, and it's retrieved with a styleable attribute that doesn't seem publicly accessible:

private int mPreferenceHeaderItemResId = 0;
...
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
...
TypedArray sa = obtainStyledAttributes(null,
            com.android.internal.R.styleable.PreferenceActivity,
            com.android.internal.R.attr.preferenceActivityStyle,
            0);
...
mPreferenceHeaderItemResId = sa.getResourceId(
    com.android.internal.R.styleable.PreferenceActivity_headerLayout,
            com.android.internal.R.layout.preference_header_item);
...
}

然后将此资源传递到专用适配器以填充标头ListView.

This resource is then passed to a private Adapter to populate the header ListView.

是否可以传递其他布局资源?

Is there a way to pass a different layout resource?

推荐答案

更新14.4.2016:通过saveInstanceState重新创建存在问题,但我发现

UPDATE 14.4.2016: there was problem with recreate by savedInstanceState, but I found another similar solution from which I used setListAdapter method code (I modified the code below).

我也解决了这个问题.我不知道以下解决方案是否正确,但是最快.因为PreferenceActivity是ListActivity的子级,所以您可以重写setListAdapter方法以将自己的适配器用于标头项目.这很丑陋,因为在PreferenceActivity.onCreate()中使用setAdapterAdapter方法将HeaderAdapter的参数设置为HeaderAdapter的新实例,因此进行调整后会忽略该实例.

I solve this problem just too. I don't know if the following solution is correct, but was the fastest. Because PreferenceActivity is child of ListActivity, you can override setListAdapter method for using own adapter for header items. This is ugly hack, because setListAdapter method is called in PreferenceActivity.onCreate() with sets adapter parameter to new instance of HeaderAdapter, so following adjustment ignore this instance.

@Override
public void setListAdapter(ListAdapter adapter) {
    int i, count;

    if (mHeaders == null) {
        mHeaders = new ArrayList<>();
        // When the saved state provides the list of headers, onBuildHeaders is not called
        // so we build it from the adapter given, then use our own adapter

        count = adapter.getCount();
        for (i = 0; i < count; ++i) {
            mHeaders.add((Header) adapter.getItem(i));
        }
    }

    super.setListAdapter(new CustomHeaderAdapter(this, mHeaders, R.layout.preference_header_item, true));
}

mHeaders属性定义为类成员

mHeaders property is defined as class member

private List<Header> mHeaders;

,并在onBuildHeaders中分配:

and is assigned in onBuildHeaders:

@Override
public void onBuildHeaders(List<Header> target) {
    mHeaders = target;
    loadHeadersFromResource(R.xml.preference_headers, target);
    ...
}

我从SDK来源复制并修改了适配器内部类和布局:

I copied and modified adapter inner class and layout from SDK source:

private static class CustomHeaderAdapter extends ArrayAdapter<Header> {
    private static class HeaderViewHolder {
        ImageView icon;
        TextView title;
        TextView summary;
    }

    private LayoutInflater mInflater;
    private int mLayoutResId;
    private boolean mRemoveIconIfEmpty;

    public CustomHeaderAdapter(Context context, List<Header> objects, int layoutResId,
                         boolean removeIconBehavior) {
        super(context, 0, objects);
        mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        mLayoutResId = layoutResId;
        mRemoveIconIfEmpty = removeIconBehavior;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        HeaderViewHolder holder;
        View view;

        if (convertView == null) {
            view = mInflater.inflate(mLayoutResId, parent, false);
            holder = new HeaderViewHolder();
            holder.icon = (ImageView) view.findViewById(R.id.icon);
            holder.title = (TextView) view.findViewById(R.id.title);
            holder.summary = (TextView) view.findViewById(R.id.summary);
            view.setTag(holder);
        } else {
            view = convertView;
            holder = (HeaderViewHolder) view.getTag();
        }

        // All view fields must be updated every time, because the view may be recycled
        Header header = getItem(position);
        if (mRemoveIconIfEmpty) {
            if (header.iconRes == 0) {
                holder.icon.setVisibility(View.GONE);
            } else {
                holder.icon.setVisibility(View.VISIBLE);
                holder.icon.setImageResource(header.iconRes);
            }
        } else {
            holder.icon.setImageResource(header.iconRes);
        }
        holder.title.setText(header.getTitle(getContext().getResources()));
        CharSequence summary = header.getSummary(getContext().getResources());
        if (!TextUtils.isEmpty(summary)) {
            holder.summary.setVisibility(View.VISIBLE);
            holder.summary.setText(summary);
        } else {
            holder.summary.setVisibility(View.GONE);
        }

        return view;
    }
}

preference_header_item.xml,其minHeight已修改:

preference_header_item.xml with modified minHeight:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:minHeight="64dp"
    android:background="?android:attr/activatedBackgroundIndicator"
    android:gravity="center_vertical"
    android:paddingRight="?android:attr/scrollbarSize"
    android:paddingEnd="?android:attr/scrollbarSize">

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

    <RelativeLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="2dip"
        android:layout_marginStart="2dip"
        android:layout_marginRight="6dip"
        android:layout_marginEnd="6dip"
        android:layout_marginTop="6dip"
        android:layout_marginBottom="6dip"
        android:layout_weight="1">

        <TextView android:id="@+id/title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:singleLine="true"
            android:textAppearance="?android:attr/textAppearanceMedium"
            android:ellipsize="marquee"
            android:fadingEdge="horizontal" />

        <TextView android:id="@+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:layout_alignStart="@android:id/title"
            android:textAppearance="?android:attr/textAppearanceSmall"
            android:ellipsize="end"
            android:maxLines="2" />

    </RelativeLayout>

</LinearLayout>

这篇关于是否可以自定义首选项标题布局?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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