Hi,
I'm trying to create a custom preference for an Android application that limits the number of items the user can select. Once the limit is reached the unselected items should be disabled and only the currently selected items are enabled.. If there are less items selected than the limit all items should be enabled.
Here are the two classes I've cobbled together. The code runs fine but no the CheckedTextView is not checked. As a result no state is maintained.
First the view class...
import android.content.Context;
import android.os.Bundle;
import android.os.Parcelable;
import android.util.AttributeSet;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.CheckedTextView;
import android.widget.ListView;
public class LimitedMultiChoiceView extends ListView
implements AdapterView.OnItemClickListener
{
private static final String SEPARATOR = "OV=I=XseparatorX=I=VO";
private static final String LIMITEDSELECTION="limitedSelection";
private static final String SUPERSTATE="superState";
private String mSelection = "";
public LimitedMultiChoiceView(Context context, CharSequence[] items, int limit)
{
this(context, null, 0, items, limit);
} // LimitedMultiChoiceView(Context context)
public LimitedMultiChoiceView(Context context, AttributeSet attrs, CharSequence[] items, int limit)
{
this(context, attrs, 0, items, limit);
} // LimitedMultiChoiceView(Context context, AttributeSet attrs)
public LimitedMultiChoiceView(Context context, AttributeSet attrs
, int defStyle, CharSequence[] items, int limit)
{
super(context, attrs, defStyle);
setAdapter(new ItemAdapter(context, android.R.layout.simple_list_item_multiple_choice, items, limit));
} // LimitedMultiChoiceView(Context context, AttributeSet attrs, int defStyle)
public String getSelection()
{
return mSelection;
} // String getSelection()
public void onItemClick(AdapterView<?> parent, View child, int position, long id)
{
// For now we don't need anything...
// we think the ItemAdapter manages what we need for each item.
} // void onItemClick(AdapterView<?> parent, View child, int position, long id)
@Override
public void onRestoreInstanceState(Parcelable toParce)
{
Bundle state=(Bundle)toParce;
super.onRestoreInstanceState(state.getParcelable(SUPERSTATE));
mSelection = state.getString(LIMITEDSELECTION);
} // void onRestoreInstanceState(Parcelable toParce)
@Override
public Parcelable onSaveInstanceState()
{
Bundle state=new Bundle();
state.putParcelable(SUPERSTATE, super.onSaveInstanceState());
state.putString(LIMITEDSELECTION, mSelection);
return(state);
} // Parcelable onSaveInstanceState()
public void setSelection(String value)
{
mSelection = value;
} // void setSelection(String value)
class ItemAdapter extends ArrayAdapter<CharSequence>
{
CharSequence[] mItems = null;
int mLimit = 1;
public ItemAdapter(Context context, int viewResId, CharSequence[] items, int limit)
{
super(context, viewResId, items);
mItems = items;
mLimit = limit;
} // ItemAdapter(Context context, int viewResId, CharSequence[] strings, int limit)
public boolean areAllItemsEnabled()
{
// Since we are in a limited selection list not all items can be
// selected so this always returns false, there is no calculating
// to do.
return false;
} // boolean areAllItemsEnabled()
public boolean isEnabled(int position)
{
boolean[] clickedIndexes = new boolean[this.getCount()];
boolean result = false;
int selectedCount = 0;
mSelection = "";
for (int item=0; item < clickedIndexes.length; item++ )
{
View itemView = this.getView(item, null, LimitedMultiChoiceView.this);
if (itemView instanceof CheckedTextView)
{
CheckedTextView check = (CheckedTextView)itemView;
// First we turn the check mark on or off...
if (item == position)
{
check.setChecked(!check.isChecked());
} // (item == position)
// Now we count how many are checked and mark our tracking array
if (check.isChecked())
{
clickedIndexes[item] = true;
mSelection += check.getText() + SEPARATOR;
}
else
{
clickedIndexes[item] = false;
} // (check.isChecked())
} // (itemView instanceof CheckedTextView)
if (clickedIndexes[item])
selectedCount++;
} // (int item=0; item< clickedIndexes.length; item++ )
if (selectedCount >= mLimit)
{
if (clickedIndexes[position])
{
result = true;
}
else
{
result = false;
} // (clickedIndexes[position])
}
else
{
result = true;
} // (selectedCount >= mLimit)
return result;
} // boolean isEnabled(int position)
} // class ItemAdapter extends ArrayAdapter<CharSequence>
} // class LimitedMultiChoiceView extends ListView
This is the preference class...
import android.content.Context;
import android.preference.ListPreference;
import android.util.AttributeSet;
import android.view.View;
public class ListPreferenceLimitedMultiSelect extends ListPreference
{
int mLimit = 3;
LimitedMultiChoiceView mList = null;
String mSelection = "";
public ListPreferenceLimitedMultiSelect(Context context)
{
this(context, null);
} // ListPreferenceLimitedMultiSelect(Context context)
public ListPreferenceLimitedMultiSelect(Context context, AttributeSet attr)
{
super(context, attr);
} // ListPreferenceLimitedMultiSelect(Context context, AttributeSet attr)
@Override
protected void onBindDialogView(View v)
{
super.onBindDialogView(v);
mList.setSelection(mSelection);
} // void onBindDialogView(View v)
@Override
protected View onCreateDialogView()
{
mList = new LimitedMultiChoiceView(getContext()
, this.getEntries(), mLimit);
return(mList);
} // View onCreateDialogView()
@Override
protected void onDialogClosed(boolean positiveResult)
{
super.onDialogClosed(positiveResult);
if (positiveResult)
{
if (callChangeListener(mList.getSelection()))
{
mSelection = mList.getSelection();
persistString(mSelection);
} // (callChangeListener(mList.getSelection()))
} // (positiveResult)
} // void onDialogClosed(boolean positiveResult)
@Override
protected void onSetInitialValue(boolean restoreValue, Object defaultValue)
{
mSelection =(restoreValue ? getPersistedString(mSelection) : (String)"");
} // void onSetInitialValue(boolean restoreValue, Object defaultValue)
} // class ListPreferenceLimitedMultiSelect extends ListPreference
Thanks,
\ ^ / i l l