views:

350

answers:

2

Hi Everyone, here's a problem that i've run into lately: I have a listview with a custom adapter class, the adapter takes in a listview and populates the listview with elements from it. Now, i'd like to have a button on each row of a listview to remove the item from it. How should i approach this problem? Is there a way to remotely trigger a method in the activity class and call notifydatachanged() method on the adapter to refresh the listview?

thanks in advance for your help and some code snippets if possible best regards peter

A: 

In the getView() method, can't you just setOnClickListener() on the button?

Something like this:

static final class MyAdapter extends BaseAdapter {

    /** override other methods here */

    @Override
    public View getView(final int position, View convertView, ViewGroup parent) {
        ViewHolder holder;

        if (convertView == null) {
            // inflate the view for row from xml file

            // keep a reference to each widget on the row.
            // here I only care about the button
            holder = new ViewHolder();
            holder.mButton = (Button)convertView.findViewById(R.id.button);
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder)convertView.getTag();
        }

        // redefine the action for the button corresponding to the row
        holder.mButton.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                // do something depending on position
                performSomeAction(position);
                // mark data as changed
                MyAdapter.this.notifyDatasetChanged();
            }
        }
    }
    static final class ViewHolder {
        // references to widgets
        Button mButton;
    }
}

If you're unsure about extending BaseAdapter, check out example List14 in ApiDemos. This techniques provides you with a flexible way to modify just about any aspect of your adapter, though it's quite some work.

Po
Hi,thanks for your help, this is pretty much what i'm doing here. I have an activity class that got an array and a list view, i got an adapter class which i pass the listview and array to. Now a row in a listview contains a button (each row), when this button gets clicked i somehow need to trigger a method inside not adapter class but class containing the activity. Do you understand?thanks peter
dusker
+1  A: 

I've done something like that:

public class MyAdapter extends Adapter {

private final ArrayList<String> items = new ArrayList<String>();

// ...

deleteRow(int position) {
    items.remove(position);
    notifyDataSetChanged();
}
//

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

    if(convertView == null) {
        Tag tag = new Tag();
        // inflate as usual, store references to widgets in the tag
        tag.button.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View v) {
                    deleteRow(position);
        }
    });
    }
    // don't forget to set the actual position for each row
    Tag tag = (Tag)convertView.getTag();
    // ...
    tag.position = position;
    // ...
}



class Tag {

    int position;

    TextView text1;
    // ...
    Button button;
}

}
alex
Pretty cool, how do you pass the modified dataset to the activity?
dusker
Why should you? `notifyDataSetChanged();` triggers ListView update.
alex
yes that's right, but is there any way to pass it over to the Activity class? or at least serialize it so it'll be accessible for other classes?
dusker
Have a getter method for `ArrayList<String> items`, probably override `notifyDataSetChanged();` to notify everyone interested. But I'd rather rethink design.
alex
Hi, thanks for answer again.How would you reference that class? It's not instantiated in ListAdapter class... is there a stack of activities accessible by a code?
dusker
Sounds like a different question to me. :)
alex