如何使用ArrayAdapter <myClass>


129
ArrayList<MyClass> myList = new ArrayList<MyClass>();

ListView listView = (ListView) findViewById(R.id.list);

ArrayAdapter<MyClass> adapter = new ArrayAdapter<MyClass>(this, R.layout.row,
    to, myList.);
listView.setAdapter(adapter);

类:MyClass

class MyClass {
    public String reason;
    public long long_val;
}

我已经在布局中创建了row.xml,但是不知道如何使用ArrayAdapter在ListView中同时显示原因和long_val。

Answers:


155

为您的课程实施自定义适配器:

public class MyClassAdapter extends ArrayAdapter<MyClass> {

    private static class ViewHolder {
        private TextView itemView;
    }

    public MyClassAdapter(Context context, int textViewResourceId, ArrayList<MyClass> items) {
        super(context, textViewResourceId, items);
    }

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

        if (convertView == null) {
            convertView = LayoutInflater.from(this.getContext())
            .inflate(R.layout.listview_association, parent, false);

            viewHolder = new ViewHolder();
            viewHolder.itemView = (TextView) convertView.findViewById(R.id.ItemView);

            convertView.setTag(viewHolder);
        } else {
            viewHolder = (ViewHolder) convertView.getTag();
        }

        MyClass item = getItem(position);
        if (item!= null) {
            // My layout has only one TextView
                // do whatever you want with your string and long
            viewHolder.itemView.setText(String.format("%s %d", item.reason, item.long_val));
        }

        return convertView;
    }
}

对于那些不太熟悉Android框架的人,这里对此进行了更详细的说明:https : //github.com/codepath/android_guides/wiki/Using-an-ArrayAdapter-with-ListView


2
抱歉,MyClass item = items.get(position)解决了错误,我不匹配变量。
Sumit M Asok

1
我已从上述代码中删除了项目字段,因为它很容易导致错误-例如,如果有人使用adapter.clear()或adapter.add(...)更改了项目的内部列表
prostynick

1
我是否正确假设textViewResourceId以上未使用?
gerrytan

8
viewHolder来自哪里?
格里2015年

2
什么是R.layout.listview_association?那是您的自定义布局吗?我可以将其替换为android.R.layout.simple_list_item_1吗?
Donato

76

您只需toString()按照http://developer.android.com/reference/android/widget/ArrayAdapter.html将方法添加到MyClass即可:

但是,如果引用了TextView,它将使用数组中每个对象的toString()进行填充。您可以添加自定义对象的列表或数组。重写对象的toString()方法,以确定将为列表中的项目显示什么文本。

class MyClass {

 @Override
 public String toString() {
  return "Hello, world.";
 }
}

20
尽管是最简单的解决方案,但(IMHO)并不是一个好主意。三个原因:如果您需要本地化,则必须进行重构。仅当您有1个适配器时才有效,如果您有2个不同的适配器MyClass,则必须进行重构。最后,将表示逻辑绑定到模型通常不是一个好主意。模型不应该知道如何将它们呈现给用户。
fernandohur 2014年

2
要解决@fernandohur的一些问题,您可以简单地为ArrayAdapter创建一个专用的视图类...因此,类型的模型类MyClass将要求您添加一个称为的专用类MyClassView,用于包装基础模型(并提供toString( )实现
沃尔玛

这个答案来自2011年,我同意@fernandohur-现在有更好的方法来处理这个问题。

我认为这是一个很好的答案,因为在很多情况下,每个类都有一个属性,而不是代表对象的名称。
约翰·弗雷迪·特鲁希略·奥尔特加

这应该是公认的答案。仅为了绑定打印名称而覆盖适配器是错误的编码。
L.Grillo

22

我认为这是最好的方法。使用通用的ArrayAdapter类并扩展自己的对象适配器非常简单,如下所示:

public abstract class GenericArrayAdapter<T> extends ArrayAdapter<T> {

  // Vars
  private LayoutInflater mInflater;

  public GenericArrayAdapter(Context context, ArrayList<T> objects) {
    super(context, 0, objects);
    init(context);
  }

  // Headers
  public abstract void drawText(TextView textView, T object);

  private void init(Context context) {
    this.mInflater = LayoutInflater.from(context);
  }

  @Override public View getView(int position, View convertView, ViewGroup parent) {
    final ViewHolder vh;
    if (convertView == null) {
      convertView = mInflater.inflate(android.R.layout.simple_list_item_1, parent, false);
      vh = new ViewHolder(convertView);
      convertView.setTag(vh);
    } else {
      vh = (ViewHolder) convertView.getTag();
    }

    drawText(vh.textView, getItem(position));

    return convertView;
  }

  static class ViewHolder {

    TextView textView;

    private ViewHolder(View rootView) {
      textView = (TextView) rootView.findViewById(android.R.id.text1);
    }
  }
}

这是您的适配器(示例):

public class SizeArrayAdapter extends GenericArrayAdapter<Size> {

  public SizeArrayAdapter(Context context, ArrayList<Size> objects) {
    super(context, objects);
  }

  @Override public void drawText(TextView textView, Size object) {
    textView.setText(object.getName());
  }

}

最后,如何初始化它:

ArrayList<Size> sizes = getArguments().getParcelableArrayList(Constants.ARG_PRODUCT_SIZES);
SizeArrayAdapter sizeArrayAdapter = new SizeArrayAdapter(getActivity(), sizes);
listView.setAdapter(sizeArrayAdapter);

我用TextView布局重力自定义ArrayAdapter创建了一个Gist:

https://gist.github.com/m3n0R/8822803


1
我真的很喜欢您的代码,但是花了我一段时间才弄清楚,为什么它与android.content.res.Resources $ NotFoundException:资源ID#0x0一起崩溃。您已经在super(..,0,..)的通用适配器调用中,其中0实际上是布局资源,该资源不存在,因此必须将其更改为其他内容。此外,要点是404
Ev0oD

最后,我最终改变了很多-下拉菜单的布局比显示项目的布局有所不同,的drawText只是呼吁微调头,而不是在其上点击..项目
Ev0oD

这应该作为通用适配器有效。你能解决这个问题吗?
cesards

是的,我成功了。我意识到您提供的解决方案与我想要的有所不同,但是我能够将您的代码用作起点并以对我想要的方式起作用的方式进行修改。感谢这段代码。
Ev0oD

默认情况下应提供。
戈达德

6

子类化ArrayAdapter并重写方法getView()以返回您自己的视图,该视图包含要显示的内容。


5

如果您不想扩展自己的母类,这是一个如何使用ArrayAdapter的简单又肮脏的示例:

class MyClass extends Activity {
    private ArrayAdapter<String> mAdapter = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        mAdapter = new ArrayAdapter<String>(getApplicationContext(),
            android.R.layout.simple_dropdown_item_1line, android.R.id.text1);

        final ListView list = (ListView) findViewById(R.id.list);
        list.setAdapter(mAdapter);

        //Add Some Items in your list:
        for (int i = 1; i <= 10; i++) {
            mAdapter.add("Item " + i);
        }

        // And if you want selection feedback:
        list.setOnItemClickListener(new OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                //Do whatever you want with the selected item
                Log.d(TAG, mAdapter.getItem(position) + " has been selected!");
            }
        });
    }
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.