可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
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!
回答1:
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:
- Just create your
Spinner
the usual way
- Define 2 equal size arrays in your
array.xml
file -- one array for labels, one array for values
- Set your
Spinner
with android:entries=\"@array/labels\"
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()];
回答2:
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) { }
});
}
}
回答3:
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
// Gets all users but replace with whatever list of users you want.
List<User> users = User.all();
ArrayAdapter userAdapter = new ArrayAdapter(this, R.layout.spinner, users);
Spinner userSpinner = (Spinner) findViewById(R.id.user);
userSpinner.setAdapter(userAdapter);
// And to get the actual User object that was selected, you can do this.
User user = (User) ( (Spinner) findViewById(R.id.user) ).getSelectedItem();
回答4:
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.
回答5:
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;
}
回答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!
回答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;
}
}
回答8:
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 ..... :)
回答9:
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.
回答10:
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:
- Which widget or composite view needs to be associated with a data structure(your class\' object) for a certain index?
- 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.
回答11:
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.
回答12:
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();
}
}