Hi there !
I spent a bit of time trying to create a spinner that would have some
disabled items, and finally found a SOLUTION ! Yay !
Romain pointed in the right direction, BUT it's not that easy.
If one try to create a specific adapter for the spinner, for
instance :
ArrayAdapter<String> spinnerAdapter = new ArrayAdapter<String>(this,
android.R.layout.simple_spinner_item,filters) {
public boolean isEnabled(int position) {
// Specific code to decide whether it's enabled or not
}
public boolean areAllItemsEnabled() {
return false;
}
};
spinner.setAdapter(spinnerAdapter);
=> DOESN'T work yet
When you click on a spinner, it opens a dialog with the items feeded
from the adapter.
BUT the adapter is wrapped by the spinner class into a DropDownAdapter
(private class inside the spinner class).
This wrapper delegates almost all method calls, except...
public boolean areAllItemsEnabled() {
return true;
}
public boolean isEnabled(int position) {
return true;
}
I don't know if there's a real reason for that. The delegate is
wrapped as as SpinnerAdapter, which doesn't hold those methods.
So the solution was pretty simple thought a bit dirty : extends
Spinner, override performClick() (this is were the adapter is
wrapped), and basically do the same thing as a spinner, but with a
patched DropDownAdapter :
/**
* A patcher spinner so that the wrapping drop down adapter delegates
* areAllItemsEnabled and isEnabled calls to the wrapped adapter.
*/
public class PatchedSpinner extends Spinner {
public PatchedSpinner(Context context, AttributeSet attrs, int
defStyle) {
super(context, attrs, defStyle);
}
public PatchedSpinner(Context context) {
super(context);
}
public PatchedSpinner(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean performClick() {
// boolean handled = super.performClick(); => this line
removed, we do not want to delegate the click to the spinner.
Context context = getContext();
final DropDownAdapter adapter = new DropDownAdapter(getAdapter
());
CharSequence mPrompt = getPrompt();
AlertDialog.Builder builder = new AlertDialog.Builder
(context);
if (mPrompt != null) {
builder.setTitle(mPrompt);
}
builder.setSingleChoiceItems(adapter, getSelectedItemPosition
(), this).show();
return true;
}
private static class DropDownAdapter implements ListAdapter,
SpinnerAdapter {
private SpinnerAdapter mAdapter;
public DropDownAdapter(SpinnerAdapter adapter) {
mAdapter = adapter;
}
public int getCount() {
return mAdapter == null ? 0 : mAdapter.getCount();
}
public Object getItem(int position) {
return mAdapter == null ? null : mAdapter.getItem
(position);
}
public long getItemId(int position) {
return mAdapter == null ? -1 : mAdapter.getItemId
(position);
}
public View getView(int position, View convertView, ViewGroup
parent) {
return getDropDownView(position, convertView, parent);
}
public View getDropDownView(int position, View convertView,
ViewGroup parent) {
return mAdapter == null ? null : mAdapter.getDropDownView
(position, convertView, parent);
}
public boolean hasStableIds() {
return mAdapter != null && mAdapter.hasStableIds();
}
public void registerDataSetObserver(DataSetObserver observer)
{
if (mAdapter != null) {
mAdapter.registerDataSetObserver(observer);
}
}
public void unregisterDataSetObserver(DataSetObserver
observer) {
if (mAdapter != null) {
mAdapter.unregisterDataSetObserver(observer);
}
}
// PATCHED
public boolean areAllItemsEnabled() {
if (mAdapter instanceof BaseAdapter) {
return ((BaseAdapter) mAdapter).areAllItemsEnabled();
} else {
return true;
}
}
// PATCHED
public boolean isEnabled(int position) {
if (mAdapter instanceof BaseAdapter) {
return ((BaseAdapter) mAdapter).isEnabled(position);
} else {
return true;
}
}
public int getItemViewType(int position) {
return 0;
}
public int getViewTypeCount() {
return 1;
}
public boolean isEmpty() {
return getCount() == 0;
}
}
}
If you think I'm doing things wrong, please let me know. This patched
spinner suits my needs.
Cheers,
Piwaï
PS : BTW, merci Romain pour le hint dans la bonne direction.
On Dec 15 2009, 7:54 am, Romain Guy <[email protected]> wrote:
> I just linked to it. ListAdapter.isEnabled(int).
>
>
>
> On Mon, Dec 14, 2009 at 10:49 PM, rexowner <[email protected]> wrote:
> > Thank you for your reply.
>
> > None of the 2 Class methods or 8 inherited methods on the page cited
> > appear to have
> > anything to do with disabling items in the list. None of the
> > subclasses
> > appear to have a way to do this either.
>
> > Maybe I am dense, but it is not at all clear how to do this.
>
> > On Dec 13, 2:10 pm, Romain Guy <[email protected]> wrote:
> >> This is performed by the
> >> adapter:http://d.android.com/reference/android/widget/ListAdapter.html#isEnab...)
>
> >> On Fri, Dec 11, 2009 at 4:50 PM, rexowner <[email protected]> wrote:
> >> > I also want to do this, and after hunting around for half a day, have
> >> > not found a way to do it,
> >> > and am moving on to some other priorities.
>
> >> > I also would be very interested in this useful behavior.
>
> >> > Sorry I can't be of more help, but if you find a way, please post.
>
> >> > Thanks!
>
> >> > On Dec 10, 4:36 pm, Keith Wiley <[email protected]> wrote:
> >> >> How do Idisable(gray out, make unselectable) an item in aSpinner?
> >> >> I tried calling View.disable() on the associated child of theSpinner,
> >> >> but it remains black text (not gray) and selectable.
>
> >> >> There must be some way of showing but leaving unselectable certain
> >> >> items in aspinner, right? This is a standard "menu" behavior that
> >> >> goes back decades. Android permits it, right? I want the user to see
> >> >> that certain options are possible under certain circumstances even if
> >> >> they are impossible at the immediate moment...exactly the way items in
> >> >> the main Android menu-button invoked menu can be visible but
> >> >> unselectable.
>
> >> >> Thanks a lot. I'm sure I'm just missing something obvious here.
>
> >> >> Cheers!
>
> >> > --
> >> > You received this message because you are subscribed to the Google
> >> > Groups "Android Developers" group.
> >> > To post to this group, send email to [email protected]
> >> > To unsubscribe from this group, send email to
> >> > [email protected]
> >> > For more options, visit this group at
> >> >http://groups.google.com/group/android-developers?hl=en
>
> >> --
> >> Romain Guy
> >> Android framework engineer
> >> [email protected]
>
> >> Note: please don't send private questions to me, as I don't have time
> >> to provide private support. All such questions should be posted on
> >> public forums, where I and others can see and answer them
>
> > --
> > You received this message because you are subscribed to the Google
> > Groups "Android Developers" group.
> > To post to this group, send email to [email protected]
> > To unsubscribe from this group, send email to
> > [email protected]
> > For more options, visit this group at
> >http://groups.google.com/group/android-developers?hl=en
>
> --
> Romain Guy
> Android framework engineer
> [email protected]
>
> Note: please don't send private questions to me, as I don't have time
> to provide private support. All such questions should be posted on
> public forums, where I and others can see and answer them
--
You received this message because you are subscribed to the Google
Groups "Android Developers" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/android-developers?hl=en