如何使用 ArrayAdapter<myClass>

Posted

技术标签:

【中文标题】如何使用 ArrayAdapter<myClass>【英文标题】:How to use ArrayAdapter<myClass> 【发布时间】:2011-01-16 23:07:59 【问题描述】:
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);

班级:我的班级

class MyClass 
    public String reason;
    public long long_val;

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

【问题讨论】:

【参考方案1】:

为您的类实现自定义适配器:

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。

【讨论】:

对不起,MyClass item = items.get(position) 解决了错误,我的变量不匹配。 我已经从上面的代码中删除了 items 字段,因为它很容易导致错误 - 例如,如果有人使用 adapter.clear() 或 adapter.add(...) 更改了内部项目列表 我是否正确假设上面没有使用textViewResourceId viewHolder 是从哪里来的? 什么是 R.layout.listview_association?那是您的自定义布局吗?我可以用 android.R.layout.simple_list_item_1 替换它吗?【参考方案2】:

您可以根据http://developer.android.com/reference/android/widget/ArrayAdapter.htmltoString() 方法添加到MyClass:

无论如何引用 TextView,它都会被数组中每个对象的 toString() 填充。您可以添加自定义对象的列表或数组。覆盖对象的 toString() 方法以确定列表中的项目将显示哪些文本。

class MyClass 

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

【讨论】:

虽然是最简单的解决方案,但这(恕我直言)不是一个好主意。三个原因:如果你需要本地化,你将不得不重构。这仅在您有 1 个适配器时才有效,如果您有 2 个用于 MyClass 的不同适配器,则必须重构。最后,将表示逻辑绑定到模型通常是个坏主意。模型不应该知道它们是如何呈现给用户的。 要解决@fernandohur 的一些问题,您可以简单地为 ArrayAdapter 创建一个专用的视图类...所以MyClass 类型的模型类需要您添加一个名为MyClassView 的专用类它包装了底层模型(并提供了toString( ) 实现 这个答案来自 2011 年,我同意 @fernandohur 的观点——现在有更好的方法来处理这个问题。 我认为这是一个很好的答案,因为很多时候每个类都有一个属性而不是代表对象的名称。 这应该是公认的答案。覆盖仅用于绑定打印名称的适配器是错误的编码。【参考方案3】:

我认为这是最好的方法。使用泛型 ArrayAdapter 类并扩展您自己的 Object 适配器,如下所示:

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

【讨论】:

我非常喜欢你的代码,但我花了一段时间才弄清楚为什么它会因 android.content.res.Resources$NotFoundException: Resource ID #0x0 而崩溃。您在 super(..,0,..) 上的通用适配器调用中,其中 0 实际上是一个布局资源,它不存在,因此必须将其更改为其他内容。此外,您的要点是 404跨度> 最后我改变了很多 - 下拉菜单的布局与显示项目的布局不同,drawText 仅在微调器标题上调用,而不是在其单击的项目上调用。 这应该作为通用适配器有效。你能解决这个问题吗? 是的,我成功了。我意识到您提供的解决方案与我想要的有所不同,但我能够以您的代码为起点并以它为我想要的方式进行修改。感谢这段代码。 这应该是默认提供的。【参考方案4】:

子类化 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!");
            
        );
    

【讨论】:

以上是关于如何使用 ArrayAdapter<myClass>的主要内容,如果未能解决你的问题,请参考以下文章

如何合并两个ArrayAdapter 一个视图?

使用带有 ArrayAdapter<Objects> 而不是 ArrayAdapter<Strings> 的 Android AutoCompleteTextView

Android之ArrayAdapter使用

如何在 Android ArrayAdapter 中使用对象数组?

如何将数据从 Arraylist 显示到自定义 ArrayAdapter

如何使用 ArrayAdapter 为 ListView 编写自定义过滤器