0

I have been working pretty much with ListViews and ExpandableListViews in android. And I know how to populate the listviews with images and text by making one customAdaper - and adapterclass extending for instance Arrayadapter.

In this app I am developing now I am using a Spinner togehter with an ArrayAdapter. In the subclass of ArrayAdapter I am overriding the getView-method to populate the views with text and images.

But the problem is that the getView is only called once - for the first listitem showed when app starts and when selecting an item from the list. Here it seem to work. But when I expanding the list through the list the getView-method is NOT called - Only the names from the string is put in the list

String[] string = {"ssun", "venus", "earth", "march"};

What I want is to have full control over the views so I can populate the whole list with my own icons, text and so on - just what used to do with ListView and Expandable ListView objects.

I know I am doing something wrong here and I can see the logic that only the first/selected item is called by the getView-method. But I want all Views to be called so I have a nice list with imageicons and manipulated text.

In the class that extends Activity

 Spinner spinner = (Spinner) findViewById(R.id.planets_spinner);

 String[] string = {"sun", "venus", "earth", "march"};
 MyArrayAdapter adapter = new MyArrayAdapter(this, string);
 adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
 spinner.setAdapter(adapter);

And the CustomAdapter

public class MyArrayAdapter extends ArrayAdapter <String> {

   private final String[] values;
   private final Context context;

   public MyArrayAdapter(Context context, String[] values) {
      super (context, R.layout.celestial_list, values);
      this.values = values;
      this.context = context;
   }

   private static class ViewHolder {
       TextView textView;
       ImageView imageView;
       ImageView infoView;
   }

   @Override
   public View getView(int position, View convertView, ViewGroup parent) {


       View view = null;
       ViewHolder viewHolder;

       if (convertView == null) {
       LayoutInflater inflater = (LayoutInflater)  context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        view = inflater.inflate(R.layout.celestial_list, parent, false);
        viewHolder = new ViewHolder();
        viewHolder.textView = (TextView) view.findViewById(R.id.label);
        viewHolder.imageView = (ImageView) view.findViewById(R.id.icon);
        view.setTag(viewHolder);
       } else {
           view = convertView;
           viewHolder = (ViewHolder) view.getTag();
       }

       System.out.println("view = " + view + " för position " + position);
       viewHolder.textView.setText(values[position]);

            switch (position) {
       case 0:
           viewHolder.imageView.setImageResource(R.drawable.sun);
           break;
       case 1:
           viewHolder.imageView.setImageResource(R.drawable.sun);
           break;
       case 2:
           viewHolder.imageView.setImageResource(R.drawable.sun);
           break;
       case 3:
           viewHolder.imageView.setImageResource(R.drawable.sun);
           break;
       }


       return view;
 }

}

Screenshot 1. It seems ok - getView is called ...

enter image description here

Screenshot 2 but only for the selected listobject - not for the rest. Only the String[] is used here

enter image description here

user3155478
  • 975
  • 1
  • 10
  • 16

2 Answers2

0

I assume (mostly sure) you are not using Fragments, hence you don't really need a custom adapter for the spinner to change the Image, where both reside inside one activity.

per http://developer.android.com/guide/topics/ui/controls/spinner.html , you should

  • make sure your Activity class implements OnItemSelectedListener ,
  • add onItemSelected and if needed onNothingSelected, put your
  • image selector code login inside onItemSelected (remember to use parent.getItemAtPosition(pos) to get current position).
Antoine Baqain
  • 392
  • 1
  • 3
0

Spinner adapters work a little bit different:

You have to add:

public class MyArrayAdapter  extends BaseAdapter implements SpinnerAdapter {

@Override
public View getDropDownView(int position, View convertView, ViewGroup parent) {

    if (convertView == null) {
        convertView = newDropDownView(parent);
    }

    bindDropDownView(position, convertView);
    return convertView;

}

protected View newDropDownView(ViewGroup parent) { ... }

protected void bindDropDownView(int position, View view) { ... }


@Override
public View getView(int position, View convertView, ViewGroup parent) { ... }


}

So the getView() will be called for the current selected item that is visible when the spinner is not expanded. While getDropDownView() will be called for each element in the list of the spinner. So that is what you are looking for.

Btw. here are some useful adapter classes (uses dagger for dependency injection, but you can just copy the code and erase the Injector class): https://github.com/sockeqwe/appkit/tree/master/adapter/src/main/java/com/hannesdorfmann/appkit/adapter

sockeqwe
  • 15,574
  • 24
  • 88
  • 144
  • ok thanks - but I get an **IllegalStateException: ArrayAdapter requires the resource ID to be a textView.** Its probably where I make a super-call to the baseclass constructor where a resourceid is passed. I pass the whole layout. Its ok as long as I use the getView method. But now when I use the getDropDownView-method I get this Exception and crash. The question is how I get a textview there? Do I have to inflate an xml-file as I do in the getView? – user3155478 Aug 03 '14 at 14:01
  • Use `BaseAdapter` instead of `ArrayAdapter` then in newDropDownView() you have to inflate your XML Layout (setup ViewHolders etc.) ... – sockeqwe Aug 03 '14 at 14:06
  • I've changed to BaseAdapter, but now the problem is that the getView and getDropDownView is not called. And I can no longer use the setDropDownViewResource(); – user3155478 Aug 03 '14 at 14:35