如何使用 simple_list_item_2 设置 ListView 的两行?

Posted

技术标签:

【中文标题】如何使用 simple_list_item_2 设置 ListView 的两行?【英文标题】:How to set both lines of a ListView using simple_list_item_2? 【发布时间】:2012-06-30 16:14:39 【问题描述】:

因此,以下将创建一个 ListView,其中行的“主要”文本视图由 values 数组填充。

ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, 
    android.R.layout.simple_list_item_2, android.R.id.text1, values);

将第三个参数更改为 android.R.id.text2 设置“辅助”文本视图。有什么简单的方法可以同时设置吗?

【问题讨论】:

【参考方案1】:

这个问题在 Google 中排名很高,但我认为给出的答案太复杂了。正如other 答案中所指出的,使用 ArrayAdapter 可以通过一个非常简单的技巧来实现所需的功能。

您可以覆盖 ArrayAdapter 的 getView 方法:

ArrayAdapter adapter = new ArrayAdapter(context, android.R.layout.simple_list_item_2, android.R.id.text1, list) 
  @Override
  public View getView(int position, View convertView, ViewGroup parent) 
    View view = super.getView(position, convertView, parent);
    TextView text1 = (TextView) view.findViewById(android.R.id.text1);
    TextView text2 = (TextView) view.findViewById(android.R.id.text2);

    text1.setText(persons.get(position).getName());
    text2.setText(persons.get(position).getAge());
    return view;
  
;

如果您没有注意到:诀窍是提供android.R.id.text1 作为(主要是不必要的)参数,否则对super 的调用将导致异常。

此外,此解决方案不使用 API 17 中已弃用的 TwoLineListItem

【讨论】:

感谢这项工作!不过,传递给 ArrayAdapterlist 变量从未真正使用过。 是的,TwoLineListItem 已被弃用,但不要认为它与 SimpleCursorAdapter 有某种关系,因为它们在 Vipul 的示例中一起使用。 SimpleCursorAdapter 是一个非常有用的通用 ListAdapter 实现,它遍历 Cursor 行,将给定的列映射到给定的布局视图。从游标填充 ListView 时,通常应该优先于编写自己的 ListAdapter。虽然,即使您不使用游标,使用 SimpleCursorAdapter 并将您的数据包装在 MatrixCursor 中也不是不可能的。 你说得对,TwoLineListItem 与 SimpleCursorAdapter 无关。我之所以包含这句话,只是因为 TwoLineListItem 用于其他两个答案。我的解决方案仅适用于简单、简短的列表。更先进的解决方案将例如也可以使用 ViewHolder 模式。 这个解决方案在大型列表上会变慢吗?它是否以某种方式使用回收? 谢谢@winne2,这个解决方案刚刚结束了5天的互联网搜索。【参考方案2】:

AFAIK simple_list_item_2 包含一个 TwoLineListItem,其中包含两个 TextView。 ArrayAdapter 在这里不起作用,您要么必须创建一个自定义适配器,要么使用支持它的适配器,如 SimpleCursorAdapter。

ListAdapter adapter = new SimpleCursorAdapter(
                 this,
                 android.R.layout.simple_list_item_2,
                 mCursor,     // Pass in the cursor to bind to.
                 new String[] People.NAME, People.COMPANY, // Array of cursor columns to bind to.
                 new int[] android.R.id.text1, android.R.id.text2);  // Parallel array of which template objects to bind to those columns.

         // Bind to our new adapter.
         setListAdapter(adapter);

或者如果你不想要 SimpleCursorAdapter 你将不得不创建自定义 ArrayAdapter 或 BaseAdapter

创建一个自定义 ArrayAdapter,将对象(有两个项目)数组应用到自定义适配器,并将其提供给 getListView.setAdapter。

覆盖 ArrayAdapter 的 getView 方法以将您的名称字符串应用到自定义列表行视图中的 TextView。

以下代码段将对您有所帮助。

SampleActivity.java

package org.sample;

import java.util.ArrayList;

import android.app.ListActivity;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
import android.widget.TwoLineListItem;

public class SampleActivity extends ListActivity 

    @Override
    public void onCreate(Bundle icicle) 
        super.onCreate(icicle);

        Person person;

        ArrayList<Person> persons = new ArrayList<Person>();

        person = new Person();
        person.setName("Vipul");
        person.setAge(20);
        persons.add(person);

        person = new Person();
        person.setName("Anil");
        person.setAge(22);
        persons.add(person);

        setListAdapter(new MyAdapter(this, persons));
    


Person.java

class Person 
    String name;
    int age;

    public String getName() 
        return name;
    

    public void setName(String name) 
        this.name = name;
    

    public int getAge() 
        return age;
    

    public void setAge(int age) 
        this.age = age;
    


MyAdapter.java

class MyAdapter extends BaseAdapter 

    private Context context;
    private ArrayList<Person> persons;

    public MyAdapter(Context context, ArrayList<Person> persons) 
        this.context = context;
        this.persons = persons;
    

    @Override
    public int getCount() 
        return persons.size();
    

    @Override
    public Object getItem(int position) 
        return persons.get(position);
    

    @Override
    public long getItemId(int position) 
        return 0;
    

    @Override
    public View getView(int position, View convertView, ViewGroup parent) 

        TwoLineListItem twoLineListItem;

        if (convertView == null) 
            LayoutInflater inflater = (LayoutInflater) context
                    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            twoLineListItem = (TwoLineListItem) inflater.inflate(
                    android.R.layout.simple_list_item_2, null);
         else 
            twoLineListItem = (TwoLineListItem) convertView;
        

        TextView text1 = twoLineListItem.getText1();
        TextView text2 = twoLineListItem.getText2();

        text1.setText(persons.get(position).getName());
        text2.setText("" + persons.get(position).getAge());

        return twoLineListItem;
    

【讨论】:

您在 Person.Java 中使用 getter/setter,这是 Google 在其性能指南中的建议。 @Fred Android 的性能提示页面建议开发人员“避免使用内部 getter/setter”,他们似乎指的是访问成员变量的方法。这并不意味着您不应该编写具有适当接口的类以供世界其他地方与之交互。在同一个技巧中,他们还指出 ProGuard 内联 getter 和 setter,这使得整点没有实际意义。 这是一个很好的答案,既提供了所需的信息,又提供了非常实用的代码应用程序。【参考方案3】:

希望对你有帮助

ArrayAdapter<CustomObject> adapter = new ArrayAdapter<CustomObject> (_context, android.R.layout.simple_list_item_2, android.R.id.text1, listCustomObject) 

                                @Override
                                public View getView(int position,
                                        View convertView, ViewGroup parent) 
                                    View view = super.getView(position, convertView, parent);

                                    TextView text1 = (TextView) view.findViewById(android.R.id.text1);
                                    TextView text2 = (TextView) view.findViewById(android.R.id.text2);

                                    text1.setText(listCustomObject.get(position).getText1());

                                    text2.setText( listCustomObject.get(position).getText2() );

                                    return view;
                                

                            ;

【讨论】:

【参考方案4】:

也可以试试....

adapter = new ArrayAdapter(this,android.R.layout.simple_list_item_2,values)
            @Override
            public View getView(int position, View convertView, ViewGroup parent)

               TwoLineListItem   row = (TwoLineListItem)super.getView(position, convertView, parent);

                row.getText1().setText(values.get***());
                row.getText2().setText(values.get****());

                return row;
            
        ;
    setAdapter(adapter);

【讨论】:

对我没用,但确实如此:sethgholson.com/2012/01/… @Timmmm super.getView() 方法可以解决这个问题。 @JasonRobinson 显然不是。它甚至没有传递那些参数。 @Timmmm 是的,但看到ArrayAdapter 中没有没有参数的getView() 方法,其意图显然是调用带有所有参数的超级getView 方法。我已经编辑了答案以消除歧义。 注意:API 17 - Android 4.2 不推荐使用 TwoLineListItem

以上是关于如何使用 simple_list_item_2 设置 ListView 的两行?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用GridLayout创建对话框?

如何清空android ListView控件的内容

ListView简单使用

Spinner的用法

在fragment中使用listview获取context

Listview 项目文本重力