How to do in-place editing in android listview?

4k Views Asked by At

Basically I have a listview with with each list item as (2 textviews and a checkbox). When a particular list item is clicked, I wanted to replace that row with a new edit-text view and some buttons. How do I implement this ? Should I use integer variables to store the current position of the selected item and load a different view OR use action motion events to get the current selected items ?

3

There are 3 best solutions below

1
On

One possible solution would be to have your row.xml file contain both (2 textviews and a checkbox) and (EditText + some Buttons) But make the EditText and Buttons default to android:visibility="gone" Then you could set an onItemClickListener() for the ListView that will call view.setVisibility() on the proper views to make them visible / invisible. This would appear to the user as though the new items are replacing the old ones in that row of the list.

0
On

EditViews are actually subclassed from TextView, so you could actually use an EditText everywhere, and then set edditable=true\false depending on your needs.

Just another possible solution, but Tim's answer is also appropriate.

1
On

Your onItemClick() should look like this:

@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
    MyAdapter myAdapter = (MyAdapter) parent.getAdapter();
    MyItem myItem = (MyItem) myAdapter.getItem(position);
    myItem.setSelected(true);  // set selected flag

    // notify the data has been changed and the view should refresh itself
    myAdapter.notifyDataSetChanged();

    // you can obtain the item view type by calling
    // myAdapter.getItemViewType(position);
    ...
}

Now override getViewTypeCount(), getItemViewType() and getView() methods in your adapter:

class MyAdapter extends ArrayAdapter<MyItem> {

    private LayoutInflater mInflater;
    private static final int VIEW_ITEM_NORMAL = 0;
    private static final int VIEW_ITEM_SELECTED = 1;
    ...

    @Override
    public int getItemViewType(int position) {
        return getItem(position).isSelected() ? VIEW_ITEM_SELECTED : VIEW_ITEM_NORMAL;
        // implement isSelected()
    }

    @Override
    public int getViewTypeCount() {
        return 2;
    }

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

        int layoutId;
        int viewType = getItemViewType(position);
        if (v == null) {
            switch (viewType) {
                case VIEW_ITEM_NORMAL:
                    layoutId = R.layout.list_item;
                    break;
                case VIEW_ITEM_SELECTED:
                    layoutId = R.layout.list_item_selected;
                    break;
                default:
                    layoutId = R.layout.list_item;
                    break;
            }
            v = mInflater.inflate(layoutId, parent, false);
        } else {
            v = convertView;
        }
        ...

If only one item can change the view at the same time, it's better to store selected flag in your adapter:

@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
    MyAdapter myAdapter = (MyAdapter) parent.getAdapter();
    myAdapter.setSelected(position);
    myAdapter.notifyDataSetChanged();
    ...
}

class MyAdapter extends ArrayAdapter<MyItem> {

    private int mSelected = -1;
    ...

    public void setSelected(int position) {
        mSelected = position;
    }

    @Override
    public int getItemViewType(int position) {
        return (mSelected == position) ? VIEW_ITEM_SELECTED : VIEW_ITEM_NORMAL;
    }
    ...

Don't forget to apply ViewHolder pattern you can see e.g. here.