Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

custom row in a listPreference?

Tags:

I am trying to create a ListPreference but somehow disable one of the items. Sort of like gray it out or something and not have the ability to choose it. It will be an upcoming feature and I want it to be in the list just not selectable.

I have created a custom ListPreference class and in that class a custom adapter, hoping to use the adapter to create what I want.

The code works, and it sets the adapter, but none of the adapter functions get called. I set breakpoints on the methods, such as getCount() but they never get called.

Here's my code. Custom ListPreference taken from http://blog.350nice.com/wp/archives/240

import android.content.Context; import android.content.DialogInterface; import android.graphics.Color; import android.preference.ListPreference; import android.util.AttributeSet; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.app.AlertDialog.Builder;  public class CustomListPreference extends ListPreference {      private boolean[] mClickedDialogEntryIndices;     CustomListPreferenceAdapter customListPreferenceAdapter = null;     Context mContext;      public CustomListPreference(Context context, AttributeSet attrs) {         super(context, attrs);         mContext = context;         mClickedDialogEntryIndices = new boolean[getEntries().length];     }      @Override     protected void onPrepareDialogBuilder(Builder builder) {         CharSequence[] entries = getEntries();         CharSequence[] entryValues = getEntryValues();         if (entries == null || entryValues == null                 || entries.length != entryValues.length) {             throw new IllegalStateException(                     "ListPreference requires an entries array "                     +"and an entryValues array which are both the same length");         }         builder.setMultiChoiceItems(entries, mClickedDialogEntryIndices,                 new DialogInterface.OnMultiChoiceClickListener() {                      public void onClick(DialogInterface dialog, int which,                             boolean val) {                         mClickedDialogEntryIndices[which] = val;                     }                 });         // setting my custom list adapter         customListPreferenceAdapter = new CustomListPreferenceAdapter(mContext);         builder.setAdapter(customListPreferenceAdapter, null);     }      private class CustomListPreferenceAdapter extends BaseAdapter {          public CustomListPreferenceAdapter(Context context) {}          public int getCount() {             return 1;         }          public Object getItem(int position) {             return position;         }          public long getItemId(int position) {             return position;         }          public View getView(int position, View convertView, ViewGroup parent) {             convertView.setBackgroundColor(Color.BLUE);             return convertView;         }     } } 
like image 704
Bob Avatar asked Dec 28 '10 21:12

Bob


1 Answers

OK I got this to work, mostly. I had to use a custom defined class that extends ListPreference. Then inside of that I had to create a custom adapter class just like you would for a ListView and set it to the builder using builder.setAdapter(). I also had to define listeners for both the RadioButtons and the ListView rows that handled unchecking of the RadioButtons and such. The only issues I still have are, my custom ListPreference has both an OK and a Cancel button where a ListPreference only has the cancel button. I don't know how to remove the OK button. Also, I can't get the rows to highlight when I click on them like they do in a regular ListPreference.

The java code for the custom ListPreference class. Be sure to mind things like your package name, the preference name (key), your entries and values for the ListPreference, and the names of your xml items.

package your.package.here;  import java.util.ArrayList; import android.content.Context; import android.content.DialogInterface; import android.content.SharedPreferences; import android.graphics.Color; import android.preference.ListPreference; import android.preference.PreferenceManager; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.CompoundButton; import android.widget.RadioButton; import android.widget.TextView; import android.app.Dialog; import android.app.AlertDialog.Builder;  public class CustomListPreference extends ListPreference {        CustomListPreferenceAdapter customListPreferenceAdapter = null;     Context mContext;     private LayoutInflater mInflater;     CharSequence[] entries;     CharSequence[] entryValues;     ArrayList<RadioButton> rButtonList;     SharedPreferences prefs;     SharedPreferences.Editor editor;      public CustomListPreference(Context context, AttributeSet attrs)     {         super(context, attrs);         mContext = context;         mInflater = LayoutInflater.from(context);         rButtonList = new ArrayList<RadioButton>();         prefs = PreferenceManager.getDefaultSharedPreferences(mContext);         editor = prefs.edit();     }      @Override     protected void onPrepareDialogBuilder(Builder builder)     {         entries = getEntries();         entryValues = getEntryValues();          if (entries == null || entryValues == null || entries.length != entryValues.length )         {             throw new IllegalStateException(                     "ListPreference requires an entries array and an entryValues array which are both the same length");         }          customListPreferenceAdapter = new CustomListPreferenceAdapter(mContext);          builder.setAdapter(customListPreferenceAdapter, new DialogInterface.OnClickListener()         {             public void onClick(DialogInterface dialog, int which)             {              }         });     }      private class CustomListPreferenceAdapter extends BaseAdapter     {                 public CustomListPreferenceAdapter(Context context)         {          }          public int getCount()         {             return entries.length;         }          public Object getItem(int position)         {             return position;         }          public long getItemId(int position)         {             return position;         }          public View getView(final int position, View convertView, ViewGroup parent)         {               View row = convertView;             CustomHolder holder = null;              if(row == null)             {                                                                                    row = mInflater.inflate(R.layout.custom_list_preference_row, parent, false);                 holder = new CustomHolder(row, position);                 row.setTag(holder);                  // do whatever you need here, for me I wanted the last item to be greyed out and unclickable                 if(position != 3)                 {                     row.setClickable(true);                     row.setOnClickListener(new View.OnClickListener()                     {                         public void onClick(View v)                         {                             for(RadioButton rb : rButtonList)                             {                                 if(rb.getId() != position)                                     rb.setChecked(false);                             }                              int index = position;                             int value = Integer.valueOf((String) entryValues[index]);                             editor.putInt("yourPref", value);                              Dialog mDialog = getDialog();                             mDialog.dismiss();                         }                     });                 }             }              return row;         }          class CustomHolder         {             private TextView text = null;             private RadioButton rButton = null;              CustomHolder(View row, int position)             {                     text = (TextView)row.findViewById(R.id.custom_list_view_row_text_view);                 text.setText(entries[position]);                 rButton = (RadioButton)row.findViewById(R.id.custom_list_view_row_radio_button);                 rButton.setId(position);                  // again do whatever you need to, for me I wanted this item to be greyed out and unclickable                 if(position == 3)                 {                     text.setTextColor(Color.LTGRAY);                     rButton.setClickable(false);                 }                  // also need to do something to check your preference and set the right button as checked                  rButtonList.add(rButton);                 rButton.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener()                 {                     public void onCheckedChanged(CompoundButton buttonView, boolean isChecked)                     {                         if(isChecked)                         {                             for(RadioButton rb : rButtonList)                             {                                 if(rb != buttonView)                                     rb.setChecked(false);                             }                              int index = buttonView.getId();                             int value = Integer.valueOf((String) entryValues[index]);                             editor.putInt("yourPref", value);                              Dialog mDialog = getDialog();                             mDialog.dismiss();                         }                     }                 });             }         }     } } 

The xml for my PreferenceActivity. This is not my full xml, took out all my other preference items for simplicity. Again, be sure to mind the package name, the custom ListPreference class must be referenced by the package name. Also mind the names of the preference and the array names that hold the entries and values.

<?xml version="1.0" encoding="utf-8"?>  <PreferenceScreen     xmlns:android="http://schemas.android.com/apk/res/android">          <PreferenceCategory                 android:title="Your Title">                  <your.package.here.CustomListPreference                     android:key="yourPref"                     android:title="Your Title"                     android:dialogTitle="Your Title"                     android:summary="Your Summary"                     android:defaultValue="1"                     android:entries="@array/yourArray"                     android:entryValues="@array/yourValues"/>          </PreferenceCategory> </PreferenceScreen> 

My xml for the dialog's list view row. In the getView method be sure to use the name of this xml file in the line that inflates this.

<?xml version="1.0" encoding="utf-8"?>  <LinearLayout     xmlns:android="http://schemas.android.com/apk/res/android"     android:orientation="vertical"     android:layout_width="fill_parent"     android:layout_height="fill_parent"     android:paddingBottom="8dip"     android:paddingTop="8dip"     android:paddingLeft="10dip"     android:paddingRight="10dip">      <TableLayout         android:id="@+id/custom_list_view_row_table_layout"         android:layout_width="fill_parent"         android:layout_height="wrap_content"         android:stretchColumns="0">          <TableRow             android:id="@+id/custom_list_view_row_table_row"             android:gravity="center_vertical"             android:layout_width="wrap_content"             android:layout_height="wrap_content">              <TextView                 android:id="@+id/custom_list_view_row_text_view"                 android:textSize="22sp"                 android:textColor="#000000"                   android:gravity="center_vertical"                 android:layout_width="160dip"                  android:layout_height="40dip" />              <RadioButton                 android:checked="false"                 android:id="@+id/custom_list_view_row_radio_button"/>         </TableRow>     </TableLayout>  </LinearLayout> 

Finally, under res/values here is my array.xml that contains the entry names and values for the ListPreference. Again, shortened mine for simplicity.

<?xml version="1.0" encoding="utf-8"?> <resources>      <string-array name="yourArray">         <item>Item 1</item>         <item>Item 2</item>         <item>Item 3</item>         <item>Item 4</item>     </string-array>      <string-array name="yourValues">         <item>0</item>         <item>1</item>         <item>2</item>         <item>3</item>     </string-array> </resources> 
like image 55
Bob Avatar answered Sep 23 '22 08:09

Bob