Home > Development > Creating Groups Or Categories For Your Settings Preferences

Creating Groups Or Categories For Your Settings Preferences

The Android API for creating a list of preference headers does not provide a means of categorizing or grouping those headers. Gouchet wrote about his investigation of the code in Android’s Settings application and offered a header adapter class that supports category headers. His class is based upon the header adapter found in the Settings.java class of that application.

While comparing Gouchet’s adapter with the adapter found in Settings.java, I noticed that Gouchet’s adapter omitted some of the code that supports view recycling. While Gouchet’s article was mainly about providing On/Off switches for a preference, a robust header adapter should handle view recycling. To keep you from having to track down Settings.java and extract the adapter code, I’ll show my version of HeaderAdapter. I did not need headers that provide On/Off switches so I left that part out. If you need such headers, use Gouchet’s download of his example.

private static class PrefsHeaderAdapter extends ArrayAdapter</pre>
<header>{

static final int HEADER_TYPE_CATEGORY = 0;
 static final int HEADER_TYPE_NORMAL = 1;

private static class HeaderViewHolder {
 ImageView icon;
 TextView title;
 TextView summary;
 }

private LayoutInflater mInflater;

public PrefsHeaderAdapter(Context context, List
<header>objects) {
 super(context, 0, objects);

mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}

@Override
 public View getView(int position, View convertView, ViewGroup parent) {
 HeaderViewHolder holder;
 Header header = getItem(position);
 int headerType = getHeaderType(header);
 View view = null;
 if (convertView == null) {
 holder = new HeaderViewHolder();

 switch (headerType) {
 case HEADER_TYPE_CATEGORY:
 view = mInflater.inflate(android.R.layout.preference_category, parent, false);
 holder.title = ((TextView) view.findViewById(android.R.id.title));
 holder.title.setText(header.getTitle(getContext().getResources()));
 view.setTag(holder);
 break;

case HEADER_TYPE_NORMAL:
 view = mInflater.inflate(R.layout.preference_header_item, parent, false);
 ImageView image = ((ImageView) view.findViewById(android.R.id.icon));
 holder.icon = image;
 image.setImageResource(header.iconRes);
 holder.title = ((TextView) view.findViewById(android.R.id.title));
 holder.title.setText(header.getTitle(getContext().getResources()));
 holder.summary = ((TextView) view.findViewById(android.R.id.summary));
 holder.summary.setText(header.getSummary(getContext().getResources()));
 view.setTag(holder);
 break;

default:
 break;
 }
 } else {
 view = convertView;
 holder = (HeaderViewHolder) view.getTag();
 }

// All view fields must be updated every time, because the view may
 // be recycled
switch (headerType) {
 case HEADER_TYPE_CATEGORY:
 holder.title.setText(header.getTitle(getContext().getResources()));
 break;
 case HEADER_TYPE_NORMAL:
 if (null != holder.icon) {
 holder.icon.setImageResource(header.iconRes);
 }
 holder.title.setText(header.getTitle(getContext().getResources()));
 CharSequence summary = header.getSummary(getContext().getResources());
 if (null != summary) {
 if (!TextUtils.isEmpty(summary)) {
 holder.summary.setVisibility(View.VISIBLE);
 holder.summary.setText(summary);
 } else {
 holder.summary.setVisibility(View.GONE);
 }
 }
 break;
 default:
 }
 return view;
 }

 public static int getHeaderType(Header header) {
 if ((header.fragment == null) && (header.intent == null)) {
 return HEADER_TYPE_CATEGORY;
 }
 return HEADER_TYPE_NORMAL;

 }
}

Using this adapter allowed me to create a grouping header labeled “CONNECTIONS” above a list of server connections in the Settings area of our app (see below for portion of the screen).

The CONNECTIONS category groups the server accounts

The CONNECTIONS category groups the server accounts

Note that if your settings allows users to add or remove items, such as accounts, then view recycling can result in an unexpected type of view holder. You might get a normal type from “convertView” but the header type is category for that position. The code in Settings.java manipulates index counters when an account is added. I added an int field to HeaderViewHolder ¬†and set it to the header type. Then if the holder retrieved from the view tag is not the same type as the header, I null it out and create a new one.

About these ads
Categories: Development Tags: ,
  1. Ed Walker
    October 28, 2013 at 2:12 am | #1

    Seems like it might work. The only problem is that there is no context. No example of where this should go or how it could or should be used….

  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: