使用适用于 Android 应用的自定义适配器将项目动态添加到列表视图

Posted

技术标签:

【中文标题】使用适用于 Android 应用的自定义适配器将项目动态添加到列表视图【英文标题】:Dynamically add items to list view using custom adapter for Android app 【发布时间】:2014-07-19 08:09:48 【问题描述】:

所以,现在我有一个自定义适配器类,它接收一组位置并将它们添加到 ListView。这一切都很好而且很花哨,但是我想在初始化之后将位置添加到这个列表视图中。例如,有人可以“添加位置”并将其添加到此 ListView。这是我的主要活动:

package com.example.listviewtest;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.ListView;

public class MainActivity extends Activity 

private ListView listView1;

@Override
public void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    Location location_data[] = new Location[]
    
        new Location(R.drawable.ic_launcher, "Location 1", "Fruit!", "2 miles", "8-4 mon-fri\nclosed sun"),
        new Location(R.drawable.ic_launcher, "Location 2", "Veggies!", "2 miles", "8-5"),
        new Location(R.drawable.ic_launcher, "Location 3", "Plants!", "2 miles", "8-5"),
        new Location(R.drawable.ic_launcher, "Location 4", "Flowers!", "2 miles", "8-5"),
        new Location(R.drawable.ic_launcher, "Location 5", "Baked Goods!", "2 miles", "8-5")
    ;

   LocationAdapter adapter = new LocationAdapter(this, 
            R.layout.listview_item_row, location_data);

   //adapter.add(new Location(R.drawable.ic_launcher, "Location 6", "Veggies!", "2 miles", "8-5"));


    listView1 = (ListView)findViewById(R.id.listView1);

    View header = (View)getLayoutInflater().inflate(R.layout.listview_header_row, null);
    listView1.addHeaderView(header);

    listView1.setAdapter(adapter);


这行得通。我现在想在用数组填充它之后做类似adapter.add(new Location(R.drawable.ic_launcher, "Location 6", "Veggies!", "2 miles", "8-5")); 的事情。

这是我的 LocationAdapter 类:

package com.example.listviewtest;

import android.app.Activity;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;

public class LocationAdapter extends ArrayAdapter<Location>

Context context; 
int layoutResourceId;    
Location data[] = null;

public LocationAdapter(Context context, int layoutResourceId, Location[] data) 
    super(context, layoutResourceId, data);
    this.layoutResourceId = layoutResourceId;
    this.context = context;
    this.data = data;


@Override
public View getView(int position, View convertView, ViewGroup parent) 
    View row = convertView;
    LocationHolder holder = null;

    if(row == null)
    
        LayoutInflater inflater = ((Activity)context).getLayoutInflater();
        row = inflater.inflate(layoutResourceId, parent, false);

        holder = new LocationHolder();
        holder.imgIcon = (ImageView)row.findViewById(R.id.imgIcon);
        holder.txtTitle = (TextView)row.findViewById(R.id.txtTitle);
        holder.details = (TextView)row.findViewById(R.id.details);
        holder.distance = (TextView)row.findViewById(R.id.distance);
        holder.hours = (TextView)row.findViewById(R.id.hours);

        row.setTag(holder);
    
    else
    
        holder = (LocationHolder)row.getTag();
    

    Location location = data[position];
    holder.txtTitle.setText(location.title);
    holder.imgIcon.setImageResource(location.icon);
    holder.details.setText(location.details);
    holder.distance.setText(location.distance);
    holder.hours.setText(location.hours);

    return row;


static class LocationHolder

    ImageView imgIcon;
    TextView txtTitle;
    TextView details;
    TextView distance;
    TextView hours;


关于如何实现这一点的任何想法?谢谢。

【问题讨论】:

【参考方案1】:
    在您的适配器中,将 Locations data[] 从数组更改为 ArrayList&lt;Location&gt; 并覆盖相应的构造函数 在您的活动中,将变量 data 设为字段(输入 ArrayList&lt;Location&gt;) 添加位置时,您可以使用data.add(location) 然后你可以在你的适配器上调用notifyDatasetChanged()

Example code.

【讨论】:

谢谢,这是我必须做的事情 如果位置数据数组设施中的数据元素具有来自互联网的媒体信息,则每次调用notifyDatasetChanged()将使应用程序 ANR。【参考方案2】:

将您的数据存储在ArrayList&lt;Location&gt; 而不仅仅是Location[],然后在您的列表适配器中创建一个公共类:

ArrayList<Location> data = new ArrayList<Location>();

@Override
public void add(Location location) 
    data.add(location);
    notifyDataSetChanged();

然后,当您想向列表中添加项目时,只需调用location_data.add(new_location)

编辑:您似乎可以从几个几乎相同的答案中进行选择。

【讨论】:

【参考方案3】:

看来您需要重写 LocationAdapter 类中的 add 方法才能将对象添加到内部列表中

@Override
public void add(Location location)

    super.add(location);
    data.add(location);

此实现要求您将数据更改为 ArrayList 而不仅仅是数组,否则您将不得不自己编写数组重新调整大小的代码。

ArrayList<Location> data = null; // Alternatively use new ArrayList<Location>();

如果您不这样做,内部数据将保持不变,并且调用 add 不会更改列表。这很糟糕,因为您使用数据变量来获取视图的值。

【讨论】:

您不必使用 adapter.notifyDataSetChanged() 因为您在 onCreate 中添加值(也就是视图尚未显示)。如果你在其他地方做,你会的。【参考方案4】:

在您的主要活动中,我建议使用 ArrayList 而不是 Location[] 以便更轻松地添加新的 Location 元素。然后,与其让 LocationAdapter 扩展 ArrayAdapter,不如让它扩展 ListAdapter,这样您就可以将 ArrayList 传递给它。

也就是说,在 MainActivity 的 addLocation(Location l) 方法中,您需要做的就是向传递给适配器的 Location[] 或 ArrayList 数据结构中添加一个元素,然后调用:

adapter.notifyDataSetChanged();

请注意,您需要将适配器设置为 MainActivity 中的成员变量,以允许在 onCreate() 之外进行访问。

【讨论】:

以上是关于使用适用于 Android 应用的自定义适配器将项目动态添加到列表视图的主要内容,如果未能解决你的问题,请参考以下文章

如何将最新数据附加到android中的自定义基本适配器列表视图?

当按下 menuItem 以在 android 中显示用于列表视图的自定义适配器时,应用程序崩溃

Android 中的自定义适配器

spinner android kotlin 的自定义适配器不可见,但在单击下拉值时可见

从android中的自定义零按钮中删除edittext中的前导零

Codemagic 不适用于 iOS 中的自定义运行脚本?