使用自定义适配器在Android应用程序中动态添加列表视图项

14

所以,现在我有一个自定义适配器类,它接收一个Locations数组并将它们添加到ListView中。这都很好,但是我想在此初始化之后向这个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;
}
}

有什么想法可以实现这个吗?感谢。

4个回答

8
  1. 在适配器中,将Locations data[]从数组更改为ArrayList<Location>并重写相应的构造函数。
  2. 在您的活动中,将变量data设置为字段(类型为ArrayList<Location>)。
  3. 当您添加位置时,可以使用data.add(location)
  4. 然后,您可以调用notifyDatasetChanged()在您的适配器上。

示例代码


谢谢,这就是我需要做的。 - user1282637
如果Location数据数组中的数据元素带有来自互联网的媒体信息,则每次调用notifyDatasetChanged()都会使应用程序ANR。 - zionpi

3

建议您将数据存储在 ArrayList<Location> 中而不是仅使用 Location[],然后在列表适配器中创建一个公共类:

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

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

那么,当您想向列表中添加一个项目时,只需调用 location_data.add(new_location)

编辑:看起来您可以从几个基本相同的答案中进行选择。


2

看起来您需要重写 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中添加值(也就是视图还没有显示)。如果你在其他地方添加,你就需要使用它。 - sotrh

1
在您的主活动中,我建议使用ArrayList< Location >而不是Location[],以便更容易添加新的Location元素。然后,不要让LocationAdapter扩展ArrayAdapter< Location >,而是让它扩展ListAdapter< Location >,这样您就可以将ArrayList< Location >传递给它。
话虽如此,在您的MainActivity中的addLocation(Location l)方法中,您只需要向传递给适配器的Location[]或ArrayList< Location >数据结构添加一个元素,然后调用:
adapter.notifyDataSetChanged();

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接