Android:如何将微调器绑定到自定义对象列表?

Nik*_*lin 117 android adapter spinner

在用户界面中,必须有一个微调器,其中包含一些名称(名称可见),每个名称都有自己的ID(ID不等于显示顺序).当用户从列表中选择名称时,必须更改变量currentID.

该应用程序包含ArrayList

User是具有ID和名称的对象:

public class User{
        public int ID;
        public String name;
    }
Run Code Online (Sandbox Code Playgroud)

我不知道的是如何创建一个显示用户名列表并将微调器项绑定到ID的微调器,这样当选择/更改微调器项时,变量currentID被设置为适当的值.

如果有人能够展示所述问题的解决方案或提供解决问题的任何链接,我将不胜感激.

谢谢!

小智 322

我知道线程很旧,但以防万一......

用户对象:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

自定义微调器适配器(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;
    }
}
Run Code Online (Sandbox Code Playgroud)

并实施:

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) {  }
        });
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 这应该是公认的答案.创建自定义适配器绝对是可行的方法. (38认同)
  • 这很好.非常好.但有一个问题.微调器现在改变了它的风格.我尝试设置一个新的xml来更改填充,文本大小但没有任何反应.我从xml中更改了它自己的微调器并且没有任何东西.唯一改变的是,如果我从SpinAdapter中更改TextView的文本大小.有没有wa保持默认的微调器样式/主题,但加载这些值? (11认同)
  • 此行的+1 :)用户user = adapter.getItem(position); (2认同)
  • 只是修改重用视图,而不是创建一个新的TextView,它应该这样做:TextView label =(TextView)super.getView(position,convertView,parent) (2认同)

Jos*_*ter 84

最简单的解决方案

在SO上搜索不同的解决方案之后,我发现以下是用于填充Spinner自定义的最简单和最干净的解决方案Objects.这是完整的实现:

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.
    }
}    
Run Code Online (Sandbox Code Playgroud)

RES /布局/ 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" />
Run Code Online (Sandbox Code Playgroud)

RES /布局/ 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>
Run Code Online (Sandbox Code Playgroud)

在你的活动中

// 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();
Run Code Online (Sandbox Code Playgroud)

  • 3年过去了,效果惊人!不敢相信人们过于复杂这件简单的事情. (4认同)

Spy*_*Zip 49

对于简单的解决方案,您只需覆盖对象中的"toString"即可

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

    @Override
    public String toString() {
        return name;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后你可以使用:

ArrayAdapter<User> dataAdapter = new ArrayAdapter<User>(mContext, android.R.layout.simple_spinner_item, listOfUsers);
Run Code Online (Sandbox Code Playgroud)

这样您的微调器将只显示用户名.


Bos*_*one 42

你可以看看这个答案.您也可以使用自定义适配器,但下面的解决方案适用于简单的情况.

这是重新发布的帖子:

所以如果你来到这里是因为你想在Spinner中同时拥有标签和值 - 这就是我如何做到的:

  1. 只需创建您Spinner通常的方式
  2. array.xml文件中定义2个相等大小的数组- 一个用于标签,一个用于值
  3. 设置你Spinnerandroid:entries="@array/labels"
  4. 当你需要一个值时,做这样的事情(不,你不必链接它):

      String selectedVal = getResources().getStringArray(R.array.values)[spinner.getSelectedItemPosition()];
    
    Run Code Online (Sandbox Code Playgroud)

  • 从可扩展性的角度来看是错误的 - 这意味着你的"对象"永远不会是动态的 - 糟糕的做法 (14认同)
  • 是否有一种优雅的方式来访问已定义的标签(与selectedVal进行比较),因此可以避免在代码中对字符串标签进行硬编码? (2认同)
  • @Bob'sBurgers你错过了这一点.我从来没有说它不起作用我说这是不好的做法,我说得对.全局变量或1个非常非常长的文件中的代码也在工作,你知道吗...顺便说一句,你应该评论旧线程,因为它们仍然出现在今天的搜索中,而ppl将使用那些(今天)错误的答案. (2认同)

Nie*_*elW 8

到目前为止,我发现的最简单的方法是:

@Override
public String toString() {
    return this.label;           
}
Run Code Online (Sandbox Code Playgroud)

现在,您可以将任何对象粘贴在微调器中,它将显示指定的标签。


小智 8

只需对Joaquin Alberto的一个小调整就可以解决样式问题.只需在自定义适配器中替换getDropDownView函数,如下所示,

@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;
    }
Run Code Online (Sandbox Code Playgroud)


Son*_*nja 6

对我来说工作正常,getResource()所需的代码如下:

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
        }

    });
Run Code Online (Sandbox Code Playgroud)

只需要确保(自己)两个数组中的值正确对齐!


小智 5

受Joaquin Alberto的启发,这对我有用:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)


小智 5

基于Joaquin Alberto(感谢)示例,但它适用于任何类型(您应该在类型中实现toString(),因此您可以格式化输出.

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;
}
}
Run Code Online (Sandbox Code Playgroud)

此外,我认为你可以替换List by Array,所以你不需要在列表中做toArray,但我有一个List ..... :)