patternjavaMinor
Simplified Android Spinner
Viewed 0 times
simplifiedspinnerandroid
Problem
I have written a simple spinner wrapper, but was wondering if any of you could think of any ways to make it more robust. It only handles strings at the moment.
```
package a.b.c;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.ArrayAdapter;
import android.widget.Spinner;
public class MySpinner extends Spinner {
// constructors (each calls initialise)
public MySpinner(Context context) {
super(context);
this.initialise();
}
public MySpinner(Context context, AttributeSet attrs) {
super(context, attrs);
this.initialise();
}
public MySpinner(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
this.initialise();
}
// declare object to hold data values
private ArrayAdapter arrayAdapter;
// add the selected item to the end of the list
public void addItem(String item) {
this.addItem(item, true);
}
public void addItem(String item, boolean select) {
arrayAdapter.add(item);
this.setEnabled(true);
if (select) this.selectItem(item);
arrayAdapter.sort(new Comparator() {
public int compare(String object1, String object2) {
return object1.compareTo(object2);
};
});
}
// remove all items from the list and disable it
public void clearItems() {
arrayAdapter.clear();
this.setEnabled(false);
}
// make the specified item selected (returns false if item not in the list)
public boolean selectItem(String item) {
boolean found = false;
for (int i = 0; i 0) {
return arrayAdapter.getItem(super.getSelectedItemPosition());
} else {
return "";
}
}
// allow the caller to use a different DropDownView, defaults to android.R.layout.simple_dropdown_item_1line
public void setDropDownViewResource(int resource) {
MySpinner:```
package a.b.c;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.ArrayAdapter;
import android.widget.Spinner;
public class MySpinner extends Spinner {
// constructors (each calls initialise)
public MySpinner(Context context) {
super(context);
this.initialise();
}
public MySpinner(Context context, AttributeSet attrs) {
super(context, attrs);
this.initialise();
}
public MySpinner(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
this.initialise();
}
// declare object to hold data values
private ArrayAdapter arrayAdapter;
// add the selected item to the end of the list
public void addItem(String item) {
this.addItem(item, true);
}
public void addItem(String item, boolean select) {
arrayAdapter.add(item);
this.setEnabled(true);
if (select) this.selectItem(item);
arrayAdapter.sort(new Comparator() {
public int compare(String object1, String object2) {
return object1.compareTo(object2);
};
});
}
// remove all items from the list and disable it
public void clearItems() {
arrayAdapter.clear();
this.setEnabled(false);
}
// make the specified item selected (returns false if item not in the list)
public boolean selectItem(String item) {
boolean found = false;
for (int i = 0; i 0) {
return arrayAdapter.getItem(super.getSelectedItemPosition());
} else {
return "";
}
}
// allow the caller to use a different DropDownView, defaults to android.R.layout.simple_dropdown_item_1line
public void setDropDownViewResource(int resource) {
Solution
This is a very nice class, and I don't wish to discredit the author (FrinkTheBrave) in any way! I do, however, want to offer a few enhancements and correct the nasty bugs that are inherent in the original.
The issues/enhancements addressed here:
o Do not insert duplicates
o Re-do selection if new row inserted
o getSelected will return null rather than empty string if nothing selected
o Proper comparison of string (a.equals(b) rather than a == b)
o Sort is now case-insensitive
o Removed 'this.' from this.foo where unneeded (which means, everywhere).
o Changed setDropDownViewResource as per comment by @seand
To explain more about the re-selection: Consider the following. Spinner currently has these items (where > indicates the selected item)
Now, we insert Bear. Unless we re-do it, the second item will remain as 'selected.' But because we inserted Bear alphabetically, the true Selected item has moved to the third position.
So, before the insertion of an non-selected String, we will save the String of the current selection (if there is one). Then, after the insertion and the sort, we will select it again.
So if I may be so bold....
The issues/enhancements addressed here:
o Do not insert duplicates
o Re-do selection if new row inserted
o getSelected will return null rather than empty string if nothing selected
o Proper comparison of string (a.equals(b) rather than a == b)
o Sort is now case-insensitive
o Removed 'this.' from this.foo where unneeded (which means, everywhere).
o Changed setDropDownViewResource as per comment by @seand
To explain more about the re-selection: Consider the following. Spinner currently has these items (where > indicates the selected item)
Antelope
> Cat
DogNow, we insert Bear. Unless we re-do it, the second item will remain as 'selected.' But because we inserted Bear alphabetically, the true Selected item has moved to the third position.
Antelope
> Bear
Cat
DogSo, before the insertion of an non-selected String, we will save the String of the current selection (if there is one). Then, after the insertion and the sort, we will select it again.
Antelope
Bear
> Cat
DogSo if I may be so bold....
package c.b.a;
import java.util.Comparator;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.ArrayAdapter;
import android.widget.Spinner;
public class AdvancedSpinner extends Spinner {
// Thanks to CodeReview: http://codereview.stackexchange.com/questions/491/simplified-android-spinner
// declare object to hold data values
private ArrayAdapter arrayAdapter;
// constructors (each call initialize)
public AdvancedSpinner(Context context) {
super(context);
initialize();
}
public AdvancedSpinner(Context context, AttributeSet attrs) {
super(context, attrs);
initialize();
}
public AdvancedSpinner(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initialize();
}
// add the selected item to the end of the list
public Boolean addItem(String item) {
return addItem(item, true);
}
public Boolean addItem(String item, boolean select) {
Boolean addFlag = true;
for (int i = 0; i () {
public int compare(String object1, String object2) {
return object1.compareToIgnoreCase(object2);
};
});
if (select)
selectItem(item);
else if (saveSelected != null)
selectItem(saveSelected);
}
return addFlag;
}
// remove all items from the list and disable it
public void clearItems() {
arrayAdapter.clear();
setEnabled(false);
}
// make the specified item selected (returns false if item not in the list)
public boolean selectItem(String item) {
boolean found = false;
for (int i = 0; i 0) {
int i = super.getSelectedItemPosition();
if (i >= 0) // An item has been selected
rtnVal = arrayAdapter.getItem(i);
}
return rtnVal;
}
// allow the caller to use a different DropDownView, defaults to android.R.layout.simple_spinner_dropdown_item
public void setDropDownViewResource(int resource) {
arrayAdapter.setDropDownViewResource(resource);
}
// internal routine to set up the array adapter, bind it to the spinner and disable it as it is empty
private void initialize() {
arrayAdapter = new ArrayAdapter(super.getContext(), android.R.layout.simple_spinner_item);
arrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
setAdapter(arrayAdapter);
setEnabled(false);
}
}Code Snippets
Antelope
> Cat
DogAntelope
> Bear
Cat
DogAntelope
Bear
> Cat
Dogpackage c.b.a;
import java.util.Comparator;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.ArrayAdapter;
import android.widget.Spinner;
public class AdvancedSpinner extends Spinner {
// Thanks to CodeReview: http://codereview.stackexchange.com/questions/491/simplified-android-spinner
// declare object to hold data values
private ArrayAdapter<String> arrayAdapter;
// constructors (each call initialize)
public AdvancedSpinner(Context context) {
super(context);
initialize();
}
public AdvancedSpinner(Context context, AttributeSet attrs) {
super(context, attrs);
initialize();
}
public AdvancedSpinner(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initialize();
}
// add the selected item to the end of the list
public Boolean addItem(String item) {
return addItem(item, true);
}
public Boolean addItem(String item, boolean select) {
Boolean addFlag = true;
for (int i = 0; i < getCount(); i++) {
if (arrayAdapter.getItem(i).equals(item)) {
// Don't add an item that's already in the list
// But we do need to mark it as "selected" if
// applicable.
addFlag = false;
if (select)
setSelection(i);
break;
}
}
if (addFlag) {
String saveSelected = null;
if (! select) {
// We need to preserve the prior selection, which may be
// messed up by our array sort operation. So we will
// save the selected item's value, and (after the insert)
// we will reinstate its selection status.
saveSelected = getSelected();
}
arrayAdapter.add(item);
setEnabled(true);
arrayAdapter.sort(new Comparator<String>() {
public int compare(String object1, String object2) {
return object1.compareToIgnoreCase(object2);
};
});
if (select)
selectItem(item);
else if (saveSelected != null)
selectItem(saveSelected);
}
return addFlag;
}
// remove all items from the list and disable it
public void clearItems() {
arrayAdapter.clear();
setEnabled(false);
}
// make the specified item selected (returns false if item not in the list)
public boolean selectItem(String item) {
boolean found = false;
for (int i = 0; i < getCount(); i++) {
if (arrayAdapter.getItem(i).equals(item)) {
setSelection(i);
found = true;
break;
}
}
return found;
}
public String getSelected() {
// return the current selected itContext
StackExchange Code Review Q#491, answer score: 7
Revisions (0)
No revisions yet.