Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spinner with empty default selected item

I'm trying to create a spinner with default empty selected item, but it displays the first item from the choices of spinner. If I add null value to my string, which is the source of choices in spinner, then after opening spinner that empty row is displayed. How should I do it? Here's code I'm using:

  String[] ch = {"Session1", "Session2", "Session3"};
  Spinner sp = (Spinner)findViewById(R.id.spinner1);
  TextView sess_name = findViewById(R.id.sessname);
  ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,android.R.layout.simple_spinner_item,ch);
  sp.setAdapter(adapter);

  adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);

  sp.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener({
      @Override
      public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
          int index = arg0.getSelectedItemPosition();
          sess_name.setText(ch[index]);

          Toast.makeText(getBaseContext(), "You have selected item : " + ch[index], Toast.LENGTH_SHORT).show();
      }
like image 929
user1484667 Avatar asked Jul 14 '12 12:07

user1484667


People also ask

What is spinner in Android with Example?

Spinners provide a quick way to select one value from a set. In the default state, a spinner shows its currently selected value. Touching the spinner displays a dropdown menu with all other available values, from which the user can select a new one.


2 Answers

Barak's solution have a problem. When you select the first item, Spinner won't call OnItemSelectedListener's onItemSelected() and refresh the empty content because the previous position and selection position both is 0.

First put a empty string at the begin of your string array:

String[] test = {" ", "one", "two", "three"};

Second build adapter, don't modify getView(), modify getDropDownView(). Set the empty View's height to 1px.

public class MyArrayAdapter extends ArrayAdapter<String> {

    private static final int ITEM_HEIGHT = ViewGroup.LayoutParams.WRAP_CONTENT;

    private int textViewResourceId;


    public MyArrayAdapter(Context context,
                          int textViewResourceId,
                          String[] objects) {
        super(context, textViewResourceId, objects);
        this.textViewResourceId = textViewResourceId;
    }

    @Override
    public View getDropDownView(int position, View convertView, @NonNull ViewGroup parent) {
        TextView textView;

        if (convertView == null) {
            textView = (TextView) LayoutInflater.from(getContext())
                   .inflate(textViewResourceId, parent, false);
        } else {
            textView = (TextView) convertView;
        }

        textView.setText(getItem(position));
        if (position == 0) {
            ViewGroup.LayoutParams layoutParams = textView.getLayoutParams();
            layoutParams.height = 1;
            textView.setLayoutParams(layoutParams);
        } else {
            ViewGroup.LayoutParams layoutParams = textView.getLayoutParams();
            layoutParams.height = ITEM_HEIGHT;
            textView.setLayoutParams(layoutParams);
        }

        return textView;
    }
}
like image 121
Jiang Qi Avatar answered Nov 10 '22 11:11

Jiang Qi


I'm a little late to the party, but here is what I did to solve this.
If the user cancels out of selecting an initial item the spinner will retain the initial empty state. Once an initial item has been selected it works as 'normal'
Works on 2.3.3+, I have not tested on 2.2 and below

First, create an adapter class...

public class EmptyFirstItemAdapter extends ArrayAdapter<String>{
    //Track the removal of the empty item
    private boolean emptyRemoved = false;

    /** Adjust the constructor(s) to fit your purposes. */
    public EmptyFirstitemAdapter(Context context, List<String> objects) {
        super(context, android.R.layout.simple_spinner_item, objects);
        setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
    }

    @Override
    public int getCount() {
        //Adjust the count based on the removal of the empty item
        if(emptyRemoved){
            return super.getCount();            
        }
        return super.getCount()-1;            
    }

    @Override
    public View getDropDownView(int position, View convertView, ViewGroup parent) {
        if(!emptyRemoved){
            // Remove the empty item the first time the dropdown is displayed.
            emptyRemoved = true;
            // Set to false to prevent auto-selecting the first item after removal.
            setNotifyOnChange(false);
            remove(getItem(0));
            // Set it back to true for future changes.
            setNotifyOnChange(true);
        }
        return super.getDropDownView(position, convertView, parent);
    }

    @Override
    public long getItemId(int position) {
        // Adjust the id after removal to keep the id's the same as pre-removal.
        if(emptyRemoved){
            return position +1;
        }
        return position;
    }

}

Here is the string array I used in strings.xml

<string-array name="my_items">
    <item></item>
    <item>Item 1</item>
    <item>Item 2</item>
</string-array>

Next, add an OnItemSelectedListener to your Spinner...

mSpinner = (Spinner) mRootView.findViewById(R.id.spinner);
String[] opts = getResources().getStringArray(R.array.my_items);
//DO NOT set the entries in XML OR use an array directly, the adapter will get an immutable List.
List<String> vals = new ArrayList<String>(Arrays.asList(opts));
final EmptyFirstitemAdapter adapter = new EmptyFirstitemAdapter(getActivity(), vals);
mSpinner.setAdapter(adapter);
mSpinner.setOnItemSelectedListener(new OnItemSelectedListener() {
    //Track that we have updated after removing the empty item
    private boolean mInitialized = false;
    @Override
    public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
        if(!mInitialized && position == 0 && id == 1){
            // User selected the 1st item after the 'empty' item was initially removed,
            // update the data set to compensate for the removed item.
            mInitialized = true;
            adapter.notifyDataSetChanged();
        }
    }

    @Override
    public void onNothingSelected(AdapterView<?> parent) {
        // Nothing to do
    }
});

It may not be a 'perfect' solution, but I hope it helps someone.

like image 31
Tom Bollwitt Avatar answered Nov 10 '22 12:11

Tom Bollwitt