【问题标题】:How to use ArrayAdapter<myClass>如何使用 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。

【问题讨论】:

    标签: android arraylist


    【解决方案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!");
                  }
              });
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2012-05-22
        • 2021-07-25
        • 2013-06-12
        • 2022-01-24
        • 1970-01-01
        • 2020-10-02
        • 1970-01-01
        • 2014-10-11
        相关资源
        最近更新 更多