151

In the user interface there has to be a spinner which contains some names (the names are visible) and each name has its own ID (the IDs are not equal to display sequence). When the user selects the name from the list the variable currentID has to be changed.

The application contains the ArrayList

Where User is an object with ID and name:

public class User{
        public int ID;
        public String name;
    }

What I don't know is how to create a spinner which displays the list of user's names and bind spinner items to IDs so when the spinner item is selected/changed the variable currentID is set to appropriate value.

I would appreciate if anyone could show the solution of the described problem or provide any link useful to solve the problem.

Thanks!

Niko Gamulin
  • 66,025
  • 95
  • 221
  • 286

17 Answers17

391

I know the thread is old, but just in case...

User object:

public class User{

    private int _id;
    private String _name;

    public User(){
        this._id = 0;
        this._name = "";
    }

    public void setId(int id){
        this._id = id;
    }

    public int getId(){
        return this._id;
    }

    public void setName(String name){
        this._name = name;
    }

    public String getName(){
        return this._name;
    }
}

Custom Spinner Adapter (ArrayAdapter)

public class SpinAdapter extends ArrayAdapter<User>{

    // Your sent context
    private Context context;
    // Your custom values for the spinner (User)
    private User[] values;

    public SpinAdapter(Context context, int textViewResourceId,
            User[] values) {
        super(context, textViewResourceId, values);
        this.context = context;
        this.values = values;
    }

    @Override
    public int getCount(){
       return values.length;
    }

    @Override
    public User getItem(int position){
       return values[position];
    }

    @Override
    public long getItemId(int position){
       return position;
    }


    // And the "magic" goes here
    // This is for the "passive" state of the spinner
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        // I created a dynamic TextView here, but you can reference your own  custom layout for each spinner item
        TextView label = (TextView) super.getView(position, convertView, parent);
        label.setTextColor(Color.BLACK);
        // Then you can get the current item using the values array (Users array) and the current position
        // You can NOW reference each method you has created in your bean object (User class)
        label.setText(values[position].getName());

        // And finally return your dynamic (or custom) view for each spinner item
        return label;
    }

    // And here is when the "chooser" is popped up
    // Normally is the same view, but you can customize it if you want
    @Override
    public View getDropDownView(int position, View convertView,
            ViewGroup parent) {
        TextView label = (TextView) super.getDropDownView(position, convertView, parent);
        label.setTextColor(Color.BLACK);
        label.setText(values[position].getName());

        return label;
    }
}

And the implementarion:

public class Main extends Activity {
    // You spinner view
    private Spinner mySpinner;
    // Custom Spinner adapter (ArrayAdapter<User>)
    // You can define as a private to use it in the all class
    // This is the object that is going to do the "magic"
    private SpinAdapter adapter;

        @Override
        public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        // Create the Users array
        // You can get this retrieving from an external source
        User[] users = new User[2];

        users[0] = new User();
        users[0].setId(1);
        users[0].setName("Joaquin");

        users[1] = new User();
        users[1].setId(2);
        users[1].setName("Alberto");

        // Initialize the adapter sending the current context
        // Send the simple_spinner_item layout
        // And finally send the Users array (Your data)
        adapter = new SpinAdapter(Main.this,
            android.R.layout.simple_spinner_item,
            users);
        mySpinner = (Spinner) findViewById(R.id.miSpinner);
        mySpinner.setAdapter(adapter); // Set the custom adapter to the spinner
        // You can create an anonymous listener to handle the event when is selected an spinner item
        mySpinner.setOnItemSelectedListener(new OnItemSelectedListener() {

            @Override
            public void onItemSelected(AdapterView<?> adapterView, View view,
                    int position, long id) {
                // Here you get the current item (a User object) that is selected by its position
                User user = adapter.getItem(position);
                // Here you can do the action you want to...
                Toast.makeText(Main.this, "ID: " + user.getId() + "\nName: " + user.getName(),
                    Toast.LENGTH_SHORT).show();
            }
            @Override
            public void onNothingSelected(AdapterView<?> adapter) {  }
        });
    }
}
Babken Vardanyan
  • 14,090
  • 13
  • 68
  • 87
Joaquin Alberto
  • 3,949
  • 2
  • 13
  • 11
  • 48
    This should be the accepted answer. Creating a custom adapter is definitely the way to go. – jamesc Jan 27 '13 at 12:50
  • 12
    This worked fine. Very nice. But one problem. The spinner now changed its style. I try to set a new xml to change the paddings, text size but nothing happens. I change the spinner it self from the xml and stil nothing. The only thing that changes is if i change the text size of the TextView from within the SpinAdapter. Is there a wa to keep the default spinner style/theme but load these kind of values? – lantonis Apr 16 '14 at 08:51
  • 1
    I've did this, but I'm getting tremendous amount of lag. While I just add 3 times. I did inflate an view to make my layout, it only contains an Icon and text. The logcat confirms me by saying `Skipped 317 frames! The application may be doing too much work on its main thread.` Any ideas? – CularBytes May 20 '15 at 19:02
  • @Joaquin Alberto I Done this exactly the way you said, now I want to set a `User` to this `spinner` , can you please tell me how can i do it? – Sasa Sep 01 '15 at 11:03
  • @Joaquin i did exactly like what you have posted, how can I set a `user` to show in `spinner`. each time I want to set different `user`, cant you please tell me how can i do this? – Sasa Sep 01 '15 at 11:24
  • 3
    +1 for this line :) User user = adapter.getItem(position); – Ahmad Alkhatib Sep 30 '15 at 10:06
  • Why does getItemId() method returns position isntead of user id? Otherwise it should be accepted answer - the one currently accepted is bad practice event tho it can be usefull to someone – Srneczek Oct 23 '15 at 10:11
  • and where is the view reusing? ... very bad implementation ... also extending ArrayAdapter is not a good practice when you are overriding almost all method from BaseAdapter ... – Selvin Dec 05 '16 at 13:00
  • 3
    Just a modification to reuse the view, instead of creating a new TextView, it should do like this: TextView label = (TextView) super.getView(position, convertView, parent) – jackcar May 05 '17 at 13:25
  • @lantonis Check this answer which I just updated, now the style is consistent with the default style of the android spinner. – Babken Vardanyan Apr 01 '18 at 15:49
127

Simplest Solution

After scouring different solutions on SO, I found the following to be the simplest and cleanest solution for populating a Spinner with custom Objects. Here's the full implementation:

User.java

public class User{
    public int ID;
    public String name;

    @Override
    public String toString() {
        return this.name; // What to display in the Spinner list.
    }
}    

res/layout/spinner.xml

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:padding="10dp"
    android:textSize="14sp"
    android:textColor="#FFFFFF"
    android:spinnerMode="dialog" />

res/layout/your_activity_view.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical">

    <Spinner android:id="@+id/user" />

</LinearLayout>

In Your Activity

List<User> users = User.all(); // This example assumes you're getting all Users but adjust it for your Class and needs.
ArrayAdapter userAdapter = new ArrayAdapter(this, R.layout.spinner, users);

Spinner userSpinner = (Spinner) findViewById(R.id.user);
userSpinner.setAdapter(userAdapter);
userSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
    @Override
    public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
        // Get the value selected by the user
        // e.g. to store it as a field or immediately call a method
        User user = (User) parent.getSelectedItem();
    }

    @Override
    public void onNothingSelected(AdapterView<?> parent) {
    }
});
Joshua Pinter
  • 45,245
  • 23
  • 243
  • 245
  • One small caveat is that this doesn't set the `currentID` as soon as the *Spinner* value changes. Most of the time you only need the value of the *Spinner* after subsequently hitting a button, such as *Submit* or *Save*, not immediately after the *Spinner* changes and if it can be avoid, this provides a much simpler solution. – Joshua Pinter Jan 16 '14 at 18:06
  • I found this to work, and by simply putting the last line somewhere else, you can get around the "problem" @JoshPinter described. – x13 Sep 16 '16 at 07:08
  • @x13 That's correct. All you need to do to get the value on change is setup a "on change" listener and then put the `getSelectedItem()` call in that. Thanks for the tip. – Joshua Pinter May 18 '17 at 20:55
  • 5
    3 years have passed and works amazing! Can't believe that people overcomplicate this simple thing. – Juan De la Cruz Dec 17 '17 at 04:43
  • 1
    @JuanDelaCruz Android and java make it easy to overcomplicate things. Simplification for the win! – Joshua Pinter Dec 18 '17 at 02:33
  • @JoshuaPinter I would add that just `new ArrayAdapter(...)` triggers a [warning](https://stackoverflow.com/questions/4204706/unchecked-call-to-arrayadapter) and `new ArrayAdapter<>(...)`is enough to avoid it... – Juan De la Cruz Dec 18 '17 at 03:23
58

For simple solutions you can just Overwrite the "toString" in your object

public class User{
    public int ID;
    public String name;

    @Override
    public String toString() {
        return name;
    }
}

and then you can use:

ArrayAdapter<User> dataAdapter = new ArrayAdapter<User>(mContext, android.R.layout.simple_spinner_item, listOfUsers);

This way your spinner will show only the user names.

SpyZip
  • 5,511
  • 4
  • 32
  • 53
47

You can look at this answer. You can also go with a custom adapter, but the solution below is fine for simple cases.

Here's a re-post:

So if you came here because you want to have both labels and values in the Spinner - here's how I did it:

  1. Just create your Spinner the usual way
  2. Define 2 equal size arrays in your array.xml file -- one array for labels, one array for values
  3. Set your Spinner with android:entries="@array/labels"
  4. When you need a value, do something like this (no, you don't have to chain it):

      String selectedVal = getResources().getStringArray(R.array.values)[spinner.getSelectedItemPosition()];
    
Community
  • 1
  • 1
Bostone
  • 36,858
  • 39
  • 167
  • 227
  • 3
    Is there an elegant way to access the defined labels (for comparison to selectedVal), so one can avoid hard-coding the string labels in code? – Anti Earth May 20 '14 at 02:57
  • This is a case of duplication of data and should be avoided. – Binoy Babu Dec 07 '14 at 12:54
  • 27
    So wrong from the scalability point of view - it means your "objects" can never be dynamic - bad practice – Srneczek Oct 23 '15 at 10:08
  • 1
    @Bostone I didnt check the time but I think it is irrelevant in this case. Adapters are there for some reason and I bet this is not about SDK change in time. It is one of reasons why they created adapters at first place. So you can serve list of complex objects, so this was in my opinion always been bad practice usable only in the very simple cases but that doesnt make it good practice. – Srneczek Oct 24 '15 at 18:37
  • @Srneczek maybe you should check the date of the answers and posts this was a good relavent answer for the user. –  Jan 07 '16 at 18:59
  • @Bob'sBurgers read what I answered to Bostone - are you saying there were no Adapters back in 09? If there were none I agree with you but as far as I can see in docs http://developer.android.com/reference/android/widget/Adapter.html it says "Added in API level 1" so I don't think time has to do anything with my comment. – Srneczek Jan 08 '16 at 14:42
  • @Srneczek lol of course there where but again obviously the answer worked for the developer asking the question. Still comes back to you as a commenter looking at the date. I've had the temptation to have a comment on old posts but I move on. –  Jan 08 '16 at 16:08
  • 4
    @Bob'sBurgers you are missing the point. I never said it is not working I said it is bad practice and I am right about that. global variables or code in 1 very, very long file are working too you know... Btw you should comment on old threads because they still appear in todays searches and ppl will use those (todays) wrong answers. – Srneczek Jan 12 '16 at 09:41
  • @Smeczek lol I didn't miss the point. It's already been accepted and the answer worked. –  Jan 12 '16 at 15:16
  • @Bob'sBurgers man seriously? Look at 133 up votes at second answer. This answer is no longer good answer and it never was a good one. You'r obviously missing point of more then just my comments. My last attempt: like it or not WORKING code doesn't have to be (and usually is not) GOOD code. I recommend you to search the term "good practice" first. – Srneczek Jan 15 '16 at 14:33
  • @Srneczek yes seriously. It's already been done and finished and worked for the person who asked the question as I'm sure they've moved on. This is not meant as a personal attack on anyone. The person who asked the question has the right to accept whatever answer they choose. I personally use BaseAdapter's but this isn't mine or yours question just saying. –  Jan 15 '16 at 15:34
  • @Bob'sBurgers what does this have to do with what I said? I said it is "bad practice" - if it works or not is irrelevant, which makes all your comments useless (thats why I am saying you are missing the point). Someone is going to edit the code the person who asked this wrote and it is usually nightmare when programmers don't follow best practices. – Srneczek Jan 15 '16 at 18:35
  • @user5530425 exactly, thank you. Thats why I am leaving comment, to direct people to the right answer which is the one by Joaquin Alberto – Srneczek Jan 16 '16 at 10:58
  • @Srneczek, I would love to see your right answer, but seems I'm having trouble finding it. – AaA Apr 01 '21 at 08:54
  • @AaA as me and user5530425 stated above, its the answer from Joaquin Alberto. – Srneczek Apr 02 '21 at 09:10
  • @Srneczek Did you notice that answer loosing UI theme because of using `simple_spinner_item`? application users don't care how you do your programming and probably nobody will ever touch that screen ever again in application lifetime. Also same users will most probably complain about the UI and its loading speed. As Answer also explains for a spinner with 2~3 fixed choices, I wouldn't go for extending classes and will use a simple and fast way. – AaA Apr 05 '21 at 02:07
  • @AaA No I have not. My comments are 5 years old. Only thing I can tell you is "best practices wherever u go". Users and clients dont care, you are the one who should. It will cost u a lot of $ if u dont. But thats general rule and ofc u gotta do tradeoffs sometimes. – Srneczek Apr 06 '21 at 06:07
10

By far the simplest way that I've found:

@Override
public String toString() {
    return this.label;           
}

Now you can stick any object in your spinner, and it will display the specified label.

NielW
  • 3,626
  • 1
  • 30
  • 38
9

Just a small tweak to Joaquin Alberto's answer can solve the style issue.Just replace the getDropDownView function in the custom adapter as below,

@Override
    public View getDropDownView(int position, View convertView, ViewGroup parent) {
        View v = super.getDropDownView(position, convertView, parent);
        TextView tv = ((TextView) v);
        tv.setText(values[position].getName());
        tv.setTextColor(Color.BLACK);
        return v;
    }
Savad KP
  • 1,625
  • 3
  • 28
  • 40
7

inspired by Joaquin Alberto, this worked for me:

public class SpinAdapter extends ArrayAdapter<User>{


    public SpinAdapter(Context context, int textViewResourceId,
            User[] values) {
        super(context, textViewResourceId, values);
    }



    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        TextView label = (TextView) super.getView(position, convertView, parent);
        label.setTextColor(Color.BLACK);
        label.setText(this.getItem(position).getName());
        return label;
    }

    @Override
    public View getDropDownView(int position, View convertView,ViewGroup parent) {
        TextView label = (TextView) super.getView(position, convertView, parent);
        label.setTextColor(Color.BLACK);
        label.setText(this.getItem(position).getName());
        return label;
    }
}
Annamaria
  • 81
  • 1
  • 4
6

Works fine for me, the code needed around the getResource() thing is as follows:

spinner = (Spinner) findViewById(R.id.spinner);
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {

        @Override
        public void onItemSelected(AdapterView<?> spinner, View v,
                int arg2, long arg3) {
            String selectedVal = getResources().getStringArray(R.array.compass_rate_values)[spinner.getSelectedItemPosition()];
            //Do something with the value
        }

        @Override
        public void onNothingSelected(AdapterView<?> arg0) {
            // TODO Auto-generated method stub
        }

    });

Just need to make sure (by yourself) the values in the two arrays are aligned properly!

Sonja
  • 169
  • 2
  • 5
5

Based on Joaquin Alberto (thanks) sample, but it works for any type (you should implement toString() in type, so you can format the output.

import java.util.List;

import android.content.Context;
import android.graphics.Color;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;

public class SpinAdapter<T> extends ArrayAdapter<T> {
private Context context;
private List<T> values;

public SpinAdapter(Context context, int textViewResourceId, List<T> values) {
    super(context, textViewResourceId, values);
    this.context = context;
    this.values = values;
}

public int getCount() {
    return values.size();
}

public T getItem(int position) {
    return values.get(position);
}

public long getItemId(int position) {
    return position;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    TextView label = new TextView(context);
    label.setTextColor(Color.BLACK);
    label.setText(values.toArray(new Object[values.size()])[position]
            .toString());
    return label;
}

@Override
public View getDropDownView(int position, View convertView, ViewGroup parent) {
    TextView label = new TextView(context);
    label.setTextColor(Color.BLACK);
    label.setText(values.toArray(new Object[values.size()])[position]
            .toString());

    return label;
}
}

Also i think you can replace List by Array so you don't need to do toArray in List, but i had a List ..... :)

4

kotlin:

data class User(
    var id: Long,
    var name : String? ){

    override fun toString(): String {
        return name
    }
}

Implementation

 mBinding.ddUser.setOnItemClickListener { parent, view, position, id ->
            val user = adapter.getItem(position)
            Log.i("idUser","${user?.idtoString()} - ${user?.name}")
        }
dieguiC
  • 41
  • 2
3

In order to understand the trick, one has to know, how Adapters work in general and ArrayAdapter in particular.

Adapters: are objects that are able to bind data structures to widgets, then these widgets are displaying that data in a List or in a Spinner.

So the two questions an Adapter answers are:

  1. Which widget or composite view needs to be associated with a data structure(your class' object) for a certain index?
  2. How to extract the data from the data structure(your class' object) and how to set field(s) i.e EditText of the widget or composite view according to this data?

ArrayAdapter's answers are:

  • Each widget (i.e row.xml OR android.R.layout.simple_spinner_item) for any index is the same, and is inflated from the resource whose ID was given to ArrayAdapter's constructor.
  • Each widget is expected to be an instance of TextView (or descendant). The widget's .setText() method will be used with the string format of the item in the supporting data structure. The string format will be obtained by invoking .toString() on the item.

CustomListViewDemo.java

public class CustomListViewDemo extends ListActivity {
  private EfficientAdapter adap;

  private static String[] data = new String[] { "0", "1", "2", "3", "4" };

  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    requestWindowFeature(Window.FEATURE_NO_TITLE);
    setContentView(R.layout.main);
    adap = new EfficientAdapter(this);
    setListAdapter(adap);
  }

  @Override
  protected void onListItemClick(ListView l, View v, int position, long id) {
    // TODO Auto-generated method stub
    super.onListItemClick(l, v, position, id);
    Toast.makeText(this, "Click-" + String.valueOf(position), Toast.LENGTH_SHORT).show();
  }

  public static class EfficientAdapter extends BaseAdapter implements Filterable {
    private LayoutInflater mInflater;
    private Bitmap mIcon1;
    private Context context;
    int firstpos=0;

    public EfficientAdapter(Context context) {
      // Cache the LayoutInflate to avoid asking for a new one each time.
      mInflater = LayoutInflater.from(context);
      this.context = context;
    }

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

      ViewHolder holder;

      if (convertView == null) {
        convertView = mInflater.inflate(R.layout.adaptor_content, null);

        holder = new ViewHolder();
        holder.sp = (Spinner) convertView.findViewById(R.id.spinner1);

        holder.ArrayAdapter_sp = new ArrayAdapter(parent.getContext(),android.R.layout.simple_spinner_item,data);
        holder.ArrayAdapter_sp.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);

        holder.sp.setAdapter( holder.ArrayAdapter_sp);
        holder.sp.setOnItemSelectedListener(new OnItemSelectedListener()
        {
            private int pos = position;
            @Override
            public void onItemSelected(AdapterView<?> arg0, View arg1,
                    int p, long arg3) 
            {
                // TODO Auto-generated method stub
                 Toast.makeText(context, "select spinner " + String.valueOf(pos)+" with value ID "+p, Toast.LENGTH_SHORT).show();    

            }

            @Override
            public void onNothingSelected(AdapterView<?> arg0)
            {
                // TODO Auto-generated method stub

            }
        });




        convertView.setTag(holder);
      } else {

        holder = (ViewHolder) convertView.getTag();
      }


      return convertView;
    }

    static class ViewHolder 
    {

        Spinner sp;
        ArrayAdapter ArrayAdapter_sp;

    }

    @Override
    public Filter getFilter() {
      // TODO Auto-generated method stub
      return null;
    }

    @Override
    public long getItemId(int position) {
      // TODO Auto-generated method stub
      return 0;
    }

    @Override
    public int getCount() {
      // TODO Auto-generated method stub
      return data.length;
    }

    @Override
    public Object getItem(int position) {
      // TODO Auto-generated method stub
      return data[position];
    }

  }

}

adaptor_content.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/lineItem"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:gravity="center_vertical" >

    <Spinner
        android:id="@+id/spinner1"
        android:layout_width="314dp"
        android:layout_height="wrap_content" />

</LinearLayout>

main.xml

<?xml version="1.0" encoding="utf-8"?>

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_height="fill_parent" android:layout_width="fill_parent"
    >

    <ListView
        android:id="@+id/android:list"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:layout_marginBottom="60dip"
        android:layout_marginTop="10dip"
        android:cacheColorHint="#00000000"
        android:drawSelectorOnTop="false" />

</RelativeLayout>

It works properly, I hope it is useful.

Mahdi Alkhatib
  • 1,954
  • 1
  • 29
  • 43
Parag Ghetiya
  • 421
  • 2
  • 14
3

Here's the complete process in Kotlin:

the spinner adapter class:

class CustomSpinnerAdapter(
    context: Context,
    textViewResourceId: Int,
    val list: List<User>
) : ArrayAdapter<User>(
    context,
    textViewResourceId,
    list
) {
    override fun getCount() = list.size

    override fun getItem(position: Int) = list[position]

    override fun getItemId(position: Int) = list[position].report.toLong()

    override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
        return (super.getDropDownView(position, convertView, parent) as TextView).apply {
            text = list[position].name
        }
    }

    override fun getDropDownView(position: Int, convertView: View?, parent: ViewGroup): View {
        return (super.getDropDownView(position, convertView, parent) as TextView).apply {
            text = list[position].name
        }
    }
}

and use it in your activity/fragment like this:

spinner.adapter = CustomerSalesSpinnerAdapter(
            context,
            R.layout.cuser_spinner_item,
            userList
        )
Amin Keshavarzian
  • 3,646
  • 1
  • 37
  • 38
3
**Easy & Simple Solution**

overide the below method in model class.


 @NonNull
 @Override
 public String toString() {
  return name; //whatever the value which you want to show in spinner list.
    }

Add the below line to set adapter.

spinner.setAdapter(new ArrayAdapter<ModelClassName>(getContext(),R.layout.item_spinner,list));
Sriraksha
  • 459
  • 1
  • 8
  • 15
2

My custom Object is

/**
 * Created by abhinav-rathore on 08-05-2015.
 */
public class CategoryTypeResponse {
    private String message;

    private int status;

    private Object[] object;

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public int getStatus() {
        return status;
    }

    public void setStatus(int status) {
        this.status = status;
    }

    public Object[] getObject() {
        return object;
    }

    public void setObject(Object[] object) {
        this.object = object;
    }

    @Override
    public String toString() {
        return "ClassPojo [message = " + message + ", status = " + status + ", object = " + object + "]";
    }

    public static class Object {
        private String name;
        private String _id;
        private String title;
        private String desc;
        private String xhdpi;
        private String hdpi;
        private String mdpi;
        private String hint;
        private String type;
        private Brands[] brands;


        public String getId() {
            return _id;
        }

        public void setId(String id) {
            this._id = id;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public String getXhdpi() {
            return xhdpi;
        }

        public void setXhdpi(String xhdpi) {
            this.xhdpi = xhdpi;
        }

        public String getHdpi() {
            return hdpi;
        }

        public void setHdpi(String hdpi) {
            this.hdpi = hdpi;
        }

        public String getMdpi() {
            return mdpi;
        }

        public void setMdpi(String mdpi) {
            this.mdpi = mdpi;
        }

        public String get_id() {
            return _id;
        }

        public void set_id(String _id) {
            this._id = _id;
        }

        public String getTitle() {
            return title;
        }

        public void setTitle(String title) {
            this.title = title;
        }

        public String getDesc() {
            return desc;
        }

        public void setDesc(String desc) {
            this.desc = desc;
        }

        public String getHint() {
            return hint;
        }

        public void setHint(String hint) {
            this.hint = hint;
        }

        public String getType() {
            return type;
        }

        public void setType(String type) {
            this.type = type;
        }

        public Brands[] getBrands() {
            return brands;
        }

        public void setBrands(Brands[] brands) {
            this.brands = brands;
        }

        @Override
        public String toString() {
            return "ClassPojo [name = " + name + "]";
        }
    }

    public static class Brands {

        private String _id;
        private String name;
        private String value;
        private String categoryid_ref;

        public String get_id() {
            return _id;
        }

        public void set_id(String _id) {
            this._id = _id;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public String getValue() {
            return value;
        }

        public void setValue(String value) {
            this.value = value;
        }

        public String getCategoryid_ref() {
            return categoryid_ref;
        }

        public void setCategoryid_ref(String categoryid_ref) {
            this.categoryid_ref = categoryid_ref;
        }

        @Override
        public String toString() {
            return  name;

        }
    }
}

I also wanted to set this object as my adapter source to my spinner without extending ArrayAdapter so that what I did was.

brandArray = mCategoryTypeResponse.getObject()[fragPosition].getBrands();

ArrayAdapter brandAdapter = new ArrayAdapter< CategoryTypeResponse.Brands>(getActivity(),
                R.layout.item_spinner, brandArray);

Now You will be able to see results in your spinner, the trick was to override toString() in you custom object, so what ever value you want to display in spinner just return that in this method.

DeltaCap019
  • 6,532
  • 3
  • 48
  • 70
1

If you don't need a separated class, i mean just a simple adapter mapped on your object. Here is my code based on ArrayAdapter functions provided.

And because you might need to add item after adapter creation (eg database item asynchronous loading).

Simple but efficient.

editCategorySpinner = view.findViewById(R.id.discovery_edit_category_spinner);

// Drop down layout style - list view with radio button         
dataAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);

// attaching data adapter to spinner, as you can see i have no data at this moment
editCategorySpinner.setAdapter(dataAdapter);
final ArrayAdapter<Category> dataAdapter = new ArrayAdapter<Category>

(getActivity(), android.R.layout.simple_spinner_item, new ArrayList<Category>(0)) {


        // And the "magic" goes here
        // This is for the "passive" state of the spinner
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            // I created a dynamic TextView here, but you can reference your own  custom layout for each spinner item
            TextView label = (TextView) super.getView(position, convertView, parent);
            label.setTextColor(Color.BLACK);
            // Then you can get the current item using the values array (Users array) and the current position
            // You can NOW reference each method you has created in your bean object (User class)
            Category item = getItem(position);
            label.setText(item.getName());

            // And finally return your dynamic (or custom) view for each spinner item
            return label;
        }

        // And here is when the "chooser" is popped up
        // Normally is the same view, but you can customize it if you want
        @Override
        public View getDropDownView(int position, View convertView,
                                    ViewGroup parent) {
            TextView label = (TextView) super.getDropDownView(position, convertView, parent);
            label.setTextColor(Color.BLACK);
            Category item = getItem(position);
            label.setText(item.getName());

            return label;
        }
    };

And then you can use this code (i couldn't put Category[] in adapter constructor because data are loaded separatly).

Note that adapter.addAll(items) refresh spinner by calling notifyDataSetChanged() in internal.

categoryRepository.getAll().observe(this, new Observer<List<Category>>() {

            @Override
            public void onChanged(@Nullable final List<Category> items) {
                dataAdapter.addAll(items);
            }
});
Zhar
  • 3,330
  • 2
  • 24
  • 25
0

I think that the best solution is the "Simplest Solution" by Josh Pinter.

This worked for me:

//Code of the activity 
//get linearLayout
LinearLayout linearLayout = (LinearLayout ) view.findViewById(R.id.linearLayoutFragment);       

LinearLayout linearLayout = new LinearLayout(getActivity());
//display css
RelativeLayout.LayoutParams params2 = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);

//create the spinner in a fragment activiy
Spinner spn = new Spinner(getActivity());

// create the adapter.
ArrayAdapter<ValorLista> spinner_adapter = new ArrayAdapter<ValorLista>(getActivity(), android.R.layout.simple_spinner_item, meta.getValorlistaList());
spinner_adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); 
spn.setAdapter(spinner_adapter);

//set the default according to value
//spn.setSelection(spinnerPosition);

linearLayout.addView(spn, params2);
//Code of the class ValorLista

import java.io.Serializable;
import java.util.List;

public class ValorLista implements Serializable{


    /**
     * 
     */
    private static final long serialVersionUID = 4930195743192929192L;
    private int id; 
    private String valor;
    private List<Metadato> metadatoList;


    public ValorLista() {
        super();
        // TODO Auto-generated constructor stub
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getValor() {
        return valor;
    }
    public void setValor(String valor) {
        this.valor = valor;
    }
    public List<Metadato> getMetadatoList() {
        return metadatoList;
    }
    public void setMetadatoList(List<Metadato> metadatoList) {
        this.metadatoList = metadatoList;
    }

    @Override
    public String toString() {  
        return getValor();
    }

}
Community
  • 1
  • 1
lopradi
  • 51
  • 1
  • 1
-1

Do:

spinner.adapter = object: ArrayAdapter<Project>(
            container.context,
            android.R.layout.simple_spinner_dropdown_item,
            state.projects
        ) {
            override fun getDropDownView(
                position: Int,
                convertView: View?,
                parent: ViewGroup
            ): View {
                val label = super.getView(position, convertView, parent) as TextView
                label.text = getItem(position)?.title
                return label
            }

            override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
                val label = super.getView(position, convertView, parent) as TextView
                label.text = getItem(position)?.title
                return label
            }
        }
Zun
  • 1,553
  • 3
  • 15
  • 26
Juliano Moraes
  • 169
  • 2
  • 3