HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavaMinor

Simplified Android Spinner

Submitted by: @import:stackexchange-codereview··
0
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.

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)

Antelope
  > Cat
    Dog


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.

Antelope
  > Bear
    Cat
    Dog


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.

Antelope
    Bear
  > Cat
    Dog


So 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
    Dog
Antelope
  > Bear
    Cat
    Dog
Antelope
    Bear
  > Cat
    Dog
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<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 it

Context

StackExchange Code Review Q#491, answer score: 7

Revisions (0)

No revisions yet.