Dynamically add items to list view using custom adapter for Android app
Asked Answered
K

4

14

So, right now I have a custom adapter class that takes in an array of Locations and adds them to a ListView. This is all fine and dandy, but I would like to add Locations to this listview after this initialization. For example, someone can "add a Location" and it will add it to this ListView. Here is my Main Activity:

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);
}
}

This works. I want to now do something like adapter.add(new Location(R.drawable.ic_launcher, "Location 6", "Veggies!", "2 miles", "8-5")); AFTER filling it with the array.

Here is my LocationAdapter class:

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;
}
}

Any ideas on how I can implement this? Thanks.

Karakalpak answered 29/5, 2014 at 17:56 Comment(0)
T
8
  1. In your adapter change the Locations data[] from array to ArrayList<Location> and override the appropriate constructor
  2. In your activity, make your variable data a field (type ArrayList<Location>)
  3. When you add a location you can use data.add(location)
  4. Then you can call notifyDatasetChanged() on your adapter

Example code.

Tambourin answered 29/5, 2014 at 18:12 Comment(1)
if data element inside Location data array facility with media info which comes from internet,call notifyDatasetChanged()every time will make the app ANR.Kelikeligot
K
3

Store your data in an ArrayList<Location> instead of just Location[], and then make a public class in your list adapter:

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

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

Then, when you want to add an item to the list, just call location_data.add(new_location).

Edit: It looks like you have your pick from several mostly identical answers.

Knighten answered 29/5, 2014 at 18:12 Comment(0)
D
2

Looks like you need to override the add method in your LocationAdapter class to add the object to the internal list

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

This implementation requires that you change data to an ArrayList instead of just an array, otherwise you would have to code the array re-sizing yourself.

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

If you don't do this, the internal data will remain unchanged and a call to add will do not change the list. This is bad because you use the data variable to get the values for the views.

Dichromatic answered 29/5, 2014 at 18:16 Comment(1)
You won't have to use the adapter.notifyDataSetChanged() because you are adding values in onCreate (aka. the view isn't showing yet). If you do it elsewhere you will.Dichromatic
B
1

In your main activity, I'd recommend using an ArrayList< Location > rather than Location[] to make it easier to add new Location elements. Then, rather than having LocationAdapter extend ArrayAdapter< Location >, have it extend ListAdapter< Location > so you can pass your ArrayList< Location > to it.

That said, all you need to do in your addLocation(Location l) method in your MainActivity, is add an element to either the Location[] or ArrayList< Location > data structure you passed to your adapter, and then call:

adapter.notifyDataSetChanged();

Note that you'll need to make your adapter a member variable in your MainActivity to allow access outside of your onCreate().

Backsheesh answered 29/5, 2014 at 18:11 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.