Skip to content

Instantly share code, notes, and snippets.

@jfsso
Created April 21, 2012 02:37
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save jfsso/2433383 to your computer and use it in GitHub Desktop.
Save jfsso/2433383 to your computer and use it in GitHub Desktop.
Android two lines ListPreference (title and subtitle)
<?xml version="1.0" encoding="utf-8"?>
<TableRow xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/custom_list_view_row_table_row"
android:gravity="center_vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingBottom="8dip"
android:paddingTop="8dip"
android:paddingLeft="10dip"
android:paddingRight="10dip">
<LinearLayout
android:orientation="vertical"
android:layout_width="0dip"
android:layout_height="fill_parent"
android:layout_weight="1"
android:padding="0dip">
<TextView
android:id="@+id/custom_list_view_row_text_view"
android:textSize="16sp"
android:textColor="#000000"
android:gravity="center_vertical"
android:layout_width="fill_parent"
android:layout_height="22dip" />
<TextView
android:id="@+id/custom_list_view_row_subtext_view"
android:textSize="12sp"
android:textColor="#000000"
android:gravity="center_vertical"
android:layout_width="fill_parent"
android:layout_height="18dip" />
</LinearLayout>
<ImageView
android:id="@+id/custom_list_view_row_selected_indicator"
android:src="@drawable/ic_action_star"
android:layout_width="wrap_content"
android:layout_height="40dip"
android:layout_gravity="center_vertical" />
</TableRow>
package jp.joao.android.preference;
import android.app.AlertDialog.Builder;
import android.content.Context;
import android.content.DialogInterface;
import android.preference.ListPreference;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.ListAdapter;
import android.widget.TextView;
public class TwoLinesListPreference extends ListPreference {
private CharSequence[] mEntries;
private CharSequence[] mEntryValues;
private CharSequence[] mEntriesSubtitles;
private String mValue;
private int mClickedDialogEntryIndex;
public TwoLinesListPreference(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onPrepareDialogBuilder(Builder builder) {
super.onPrepareDialogBuilder(builder);
mEntries = getEntries();
mEntryValues = getEntryValues();
mEntriesSubtitles = getEntriesSubtitles();
mValue = getValue();
mClickedDialogEntryIndex = getValueIndex();
if (mEntries == null || mEntryValues == null || mEntriesSubtitles == null) {
throw new IllegalStateException(
"ListPreference requires an entries array and an entryValues array.");
}
String[] mEntriesString = (String[]) mEntries;
// adapter
ListAdapter adapter = new ArrayAdapter<String>(
getContext(), R.layout.two_lines_list_preference_row, mEntriesString) {
ViewHolder holder;
class ViewHolder {
TextView title;
TextView subTitle;
ImageView selectedIndicator;
}
public View getView(int position, View convertView, ViewGroup parent) {
final LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (convertView == null) {
convertView = inflater.inflate(R.layout.two_lines_list_preference_row, null);
holder = new ViewHolder();
holder.title = (TextView) convertView.findViewById(R.id.custom_list_view_row_text_view);
holder.subTitle = (TextView) convertView.findViewById(R.id.custom_list_view_row_subtext_view);
holder.selectedIndicator = (ImageView) convertView.findViewById(R.id.custom_list_view_row_selected_indicator);
convertView.setTag(holder);
} else {
// view already defined, retrieve view holder
holder = (ViewHolder) convertView.getTag();
}
holder.title.setText(mEntries[position]);
holder.subTitle.setText(mEntriesSubtitles[position]);
holder.selectedIndicator.setVisibility(position == mClickedDialogEntryIndex ? View.VISIBLE : View.GONE);
return convertView;
}
};
builder.setAdapter(adapter, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
mClickedDialogEntryIndex = which;
/*
* Clicking on an item simulates the positive button click, and
* dismisses the dialog.
*/
TwoLinesListPreference.this.onClick(dialog, DialogInterface.BUTTON_POSITIVE);
dialog.dismiss();
}
});
/*
* The typical interaction for list-based dialogs is to have
* click-on-an-item dismiss the dialog instead of the user having to
* press 'Ok'.
*/
builder.setPositiveButton(null, null);
}
@Override
protected void onDialogClosed(boolean positiveResult) {
super.onDialogClosed(positiveResult);
if (positiveResult && mClickedDialogEntryIndex >= 0 && mEntryValues != null) {
String value = mEntryValues[mClickedDialogEntryIndex].toString();
if (callChangeListener(value)) {
setValue(value);
}
}
}
/**
* Returns the index of the given value (in the entry values array).
*
* @param value The value whose index should be returned.
* @return The index of the value, or -1 if not found.
*/
public int findIndexOfValue(String value) {
if (value != null && mEntryValues != null) {
for (int i = mEntryValues.length - 1; i >= 0; i--) {
if (mEntryValues[i].equals(value)) {
return i;
}
}
}
return -1;
}
private int getValueIndex() {
return findIndexOfValue(mValue);
}
public CharSequence[] getEntriesSubtitles() {
return mEntriesSubtitles;
}
public void setEntriesSubtitles(CharSequence[] mEntriesSubtitles) {
this.mEntriesSubtitles = mEntriesSubtitles;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment