【问题标题】:Displaying and ArrayList of LinearLayout objects in a ListView by extending ArrayAdapter通过扩展 ArrayAdapter 在 ListView 中显示和显示 LinearLayout 对象的 ArrayList
【发布时间】:2014-05-27 03:52:30
【问题描述】:

我有一个线性布局的 ArrayList。每个 LinearLayout 都包含几个以编程方式添加的其他视图。

我想要做的是在 ListView 中显示这些 LinearLayout 视图,以便利用 ListView 的能力只呈现需要的内容。

我的原始代码使用了一个在布局 xml 中定义的 ScrollView,我以编程方式将我的每个 LinearLayouts 添加到 ScrollView 中,它运行良好。

我现在用 ListView 替换了 xml 中的 ScrollView,并添加了一个适配器。

在下面的示例中,我简化了所有尝试并找到问题的根源。当适配器的 getView 方法返回 LinearLayout 时,我得到一个 ClassCastException。

活动布局 xml (trend_scrollable.xml):

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal" >
        <ListView
              android:id="@+id/trend_listview"
              android:layout_height="fill_parent"
              android:layout_width="fill_parent">
         </ListView>
</LinearLayout>

每一行的布局(simple_chart_item.xml):

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/chartItem"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" 
    android:orientation="horizontal" >
</LinearLayout>

适配器:

    public class ChartArrayAdapter extends ArrayAdapter<LinearLayout>
    {
        ArrayList<LinearLayout> layoutList;

        public ChartArrayAdapter(Context context, ArrayList<LinearLayout> list)
        {
            super(context, R.layout.simple_chart_item, list);
            this.layoutList = new ArrayList<LinearLayout>(list);
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent)
        {
            return layoutList.get(position);
        }

        @Override
        public int getCount()
        {
            return this.layoutList != null ? this.layoutList.size() : 0;
        }
    }

活动:

    @Override
protected void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    this.setContentView(R.layout.trend_scrollable);

    ListView layout = (ListView) findViewById(R.id.trend_listview);

    ArrayList<LinearLayout> layoutList = new ArrayList<LinearLayout>();

    for (int i = 0; i < 2; i++)
    {
        layoutList.add(getDemoView(GlobalVars.getContext(), i));            
    }

    ChartArrayAdapter adapter = new ChartArrayAdapter(this, layoutList);
    layout.setAdapter(adapter);
}

有人可以帮我解决这个问题吗?我已经简化了适配器的 getView 方法,总是只返回一个 LinearLayout 视图,我认为这意味着总是会创建一个新视图。我怀疑返回的 LinearView 可能有问题并将其与“simple_chart_layout.xml”匹配,也许..

【问题讨论】:

标签: java android listview adapter


【解决方案1】:

ListView 的目的有两个:按需创建视图,以及回收视图。按需创建避免了在一次只显示一部分视图时必须预先创建所有视图。视图回收避免了在用户滚动列表时必须将所有这些视图保留在内存中。

现在您正在onCreate 中创建一大堆视图并将它们存储在适配器中,这完全违背了上述两个目的。这并不比您之前使用 ScrollView 所做的更好。

您通常会做的是给适配器一些数据(如字符串列表),然后它会在逻辑上根据需要将该数据绑定到视图。在getView() 中,您将创建行布局(通过膨胀一个全新的布局或重新使用提供的convertView 参数),用数据填充它,然后返回它。看起来像这样:

LayoutInflater inflater; // initialize in adapter's constructor

@Override
public View getView(int position, View convertView, ViewGroup container) {
    if (convertView == null) {
        // inflate if not recycled
        convertView = inflater.inflate(R.layout.your_list_item, container, false);
    }

    // populate the views
    TextView sampleText = (TextView) convertView.findViewById(R.id...);
    sampleText.setText(...); // based on position argument and what data your adapter holds

    return convertView;
}

这是基本版本;通常,您还可以使用ViewHolder pattern 通过消除对findViewById 调用的需要来提高性能。

我总是建议人们观看The World of ListView。您似乎已经对 Android 有一些经验,但您可能会觉得它很有帮助。

【讨论】:

  • 感谢您的回答。你说过我的实现远非理想,这是正确的。 youtube上谷歌教程的链接填补了我理解中的一些空白。我的想法是基于从构建滚动视图的所有视图到正确实现的列表视图的迭代步骤,所以我的问题是为什么这个例子不起作用。您可以创建您喜欢的任何视图(以编程方式,因此不限于 xml 布局)并将其返回。我的回答解决了我的问题。我现在将根据需要(按照建议)构建每个视图,然后使用 ViewHolder 模式。
  • 您当然可以通过编程方式创建视图,但当它不为空时,您仍应重新使用回收的convertView
【解决方案2】:

在正确查看调试消息后,我的示例开始工作。我正在做的是使用下面的代码创建一个演示 LinearView:

private static LinearLayout getDemoView(Context context, int i)
{
    LinearLayout containerView = new LinearLayout(context);
    LinearLayout.LayoutParams containerParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
    containerView.setLayoutParams(containerParams);
    containerView.setOrientation(LinearLayout.HORIZONTAL);

    TextView titleLabelView = new TextView(context, null);
    titleLabelView.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT));
    titleLabelView.setText("Demo text view 1 - " + Integer.toString(i)); 
    containerView.addView(titleLabelView);

    TextView bodyLabelView = new TextView(context, null);
    bodyLabelView.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT));
    bodyLabelView.setText("Demo text view 2 - " + Integer.toString(i)); 
    containerView.addView(bodyLabelView);

    return containerView;
}

此代码只是创建一个 LinearView 并在其中放置两个 TextView,其中包含一些文本。

我在 LogCat 中遇到的错误是:

java.lang.ClassCastException: android.widget.LinearLayout$LayoutParams cannot be cast to android.widget.AbsListView$LayoutParams

通过注释掉以下几行,我的代码起作用了:

LinearLayout.LayoutParams containerParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
containerView.setLayoutParams(containerParams);

剩下的代码是:

适配器:

public class ChartArrayAdapter extends ArrayAdapter<LinearLayout>
{
    public ChartArrayAdapter(Context context, ArrayList<LinearLayout> list)
    {
        super(context, R.layout.simple_chart_item, list);
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent)
    {
        return this.getItem(position);
    }
}

活动:

@Override
protected void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    this.setContentView(R.layout.trend_scrollable);

    ListView layout = (ListView) findViewById(R.id.trend_listview);

    ArrayList<LinearLayout> layoutList = new ArrayList<LinearLayout>();

    for (int i = 0; i < 2; i++)
    {
        layoutList.add(getDemoView(this, i));            
    }

    ChartArrayAdapter adapter = new ChartArrayAdapter(this, layoutList);
    layout.setAdapter(adapter);
}

问题是我将 LinearLayout 参数添加到进入 ListView 的视图中。除了我之外没有人会知道的事情,因为我没有将那部分代码放在我最初的问题中 - 我很抱歉。

我在这里给出的是一个非常糟糕的 ListView 实现,因为这是从已经创建了所有 LinearView 的 ScrollView 到由适配器动态创建视图的 ListView 的中间步骤.这个练习对我很有用,但对其他人可能没有用,尽管它确实证明了你可以将任何你喜欢的数组列表传递给自定义适配器,然后在从 getView 返回时创建你喜欢的任何视图。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-27
    • 2018-07-12
    • 2017-08-15
    • 1970-01-01
    相关资源
    最近更新 更多