Friday, January 9, 2015

Add/Remove items to custom ListView programmatically

This example show how to add/remove items to/from custom ListView, using Java code at run-time. Modify from last example of Custom ListView with ImageView.

Long click item in ListView1 (left), the item will be removed from ListView1 and added to ListView2 (right).


MainActivity.java
package com.example.androidimageviewlist;

import java.util.ArrayList;
import java.util.List;

import android.support.v7.app.ActionBarActivity;
import android.app.Activity;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends ActionBarActivity {
 
 public class Item {
  Drawable ItemDrawable;
  String ItemString;
  Item(Drawable drawable, String t){
   ItemDrawable = drawable;
   ItemString = t;
  }
 }
 
 static class ViewHolder {
  ImageView icon;
  TextView text; 
 }

 public class ItemsListAdapter extends BaseAdapter {
  
  private Context context;
  private List<Item> list;

  ItemsListAdapter(Context c, List<Item> l){
   context = c;
   list = l;
  }

  @Override
  public int getCount() {
   return list.size();
  }

  @Override
  public Object getItem(int position) {
   return list.get(position);
  }

  @Override
  public long getItemId(int position) {
   return position;
  }

  @Override
  public View getView(int position, View convertView, ViewGroup parent) {
   View rowView = convertView;
   
      // reuse views
      if (rowView == null) {
       LayoutInflater inflater = ((Activity) context).getLayoutInflater();
       rowView = inflater.inflate(R.layout.row, null);

       ViewHolder viewHolder = new ViewHolder();
       viewHolder.icon = (ImageView) rowView.findViewById(R.id.rowImageView);
       viewHolder.text = (TextView) rowView.findViewById(R.id.rowTextView);
       rowView.setTag(viewHolder); 
      }

      ViewHolder holder = (ViewHolder) rowView.getTag();
      holder.icon.setImageDrawable(list.get(position).ItemDrawable);
      holder.text.setText(list.get(position).ItemString);

      return rowView;
  }
  
  public List<Item> getList(){
   return list;
  }
 }

 List<Item> items1, items2;
 ListView listView1, listView2;
 ItemsListAdapter myItemsListAdapter1, myItemsListAdapter2;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  listView1 = (ListView)findViewById(R.id.listview1);
  listView2 = (ListView)findViewById(R.id.listview2);
  
  initItems();
  myItemsListAdapter1 = new ItemsListAdapter(this, items1);
  myItemsListAdapter2 = new ItemsListAdapter(this, items2);
  listView1.setAdapter(myItemsListAdapter1);
  listView2.setAdapter(myItemsListAdapter2);

  listView1.setOnItemClickListener(listOnItemClickListener);
  listView2.setOnItemClickListener(listOnItemClickListener);
  
  listView1.setOnItemLongClickListener(new OnItemLongClickListener(){

   @Override
   public boolean onItemLongClick(AdapterView<?> parent, View view,
     int position, long id) {
    Item selectedItem = (Item)(parent.getItemAtPosition(position));
    
    ItemsListAdapter associatedAdapter = (ItemsListAdapter)(parent.getAdapter());
    List<Item> associatedList = associatedAdapter.getList();
    Item associatedItem = associatedList.get(position);
    if(removeItemToList(associatedList, associatedItem)){
     
     view.invalidate();
     associatedAdapter.notifyDataSetChanged();

     ItemsListAdapter list2Adapter = (ItemsListAdapter)(listView2.getAdapter());
     List<Item> list2List = list2Adapter.getList();

     addItemToList(list2List, selectedItem);
     list2Adapter.notifyDataSetChanged();
    }
    
    return true;
   }});

 }
 
 OnItemClickListener listOnItemClickListener = new OnItemClickListener(){

  @Override
  public void onItemClick(AdapterView<?> parent, View view, int position,
    long id) {
   Toast.makeText(MainActivity.this, 
     ((Item)(parent.getItemAtPosition(position))).ItemString, 
     Toast.LENGTH_SHORT).show();
  }
  
 };

 private void initItems(){
  items1 = new ArrayList<Item>();
  items2 = new ArrayList<Item>();
  
  TypedArray arrayDrawable = getResources().obtainTypedArray(R.array.resicon);
  TypedArray arrayText = getResources().obtainTypedArray(R.array.restext);
  
  for(int i=0; i<arrayDrawable.length(); i++){
   Drawable d = arrayDrawable.getDrawable(i);
   String s = arrayText.getString(i);
   Item item = new Item(d, s);
   items1.add(item);
  }
  
  arrayDrawable.recycle();
  arrayText.recycle();
 }
 
 private boolean removeItemToList(List<Item> l, Item it){
  boolean result = l.remove(it);
  return result;
 }
 
 private boolean addItemToList(List<Item> l, Item it){
  boolean result = l.add(it);
  return result;
 }

}

Modify activity_main.xml to have two ListView.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="4dp"
    tools:context="com.example.androidimageviewlist.MainActivity" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:autoLink="web"
        android:text="http://android-er.blogspot.com/"
        android:textStyle="bold" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="horizontal"
        android:background="@android:color/background_dark" >

        <LinearLayout
            android:id="@+id/pane1"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:layout_margin="4dp"
            android:background="@android:color/background_light"
            android:orientation="vertical" >

            <ListView
                android:id="@+id/listview1"
                android:layout_width="match_parent"
                android:layout_height="wrap_content" />
        </LinearLayout>

        <LinearLayout
            android:id="@+id/pane2"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:layout_margin="4dp"
            android:background="@android:color/background_light"
            android:orientation="vertical" >

            <ListView
                android:id="@+id/listview2"
                android:layout_width="match_parent"
                android:layout_height="wrap_content" />
        </LinearLayout>
    </LinearLayout>

</LinearLayout>

/res/layout/row.xml and /res/values/arrays.xml, refer to last post.

download filesDownload the files.


Nexy:
Drag and Drop items between ListView


Re-test@2015-10-20:
Somebody complain that it does not work, I download the Eclipse project, and import to Android Studio, and test it again, on Emulators running Lollipop Android 5.1 API 22 and Jelly Bean Android 4.1 API 16.

And found it work as expected: Long-click on left ListView to delete the item and add to the right ListView.


3 comments:

Unknown said...

item selected from first listview is not added to second one only toast appears, even item selected is also not removed from the first one.

Andr.oid Eric said...

Hello Unknown,

Would you let me know what machine you tested? I test it again and work as expected. Please see the updated video.

J Bilegjargal said...

too heavy coding