Showing posts with label Android code sample: ListView. Show all posts
Showing posts with label Android code sample: ListView. Show all posts

Thursday, March 30, 2017

Android ListView with CheckBox

This example show how to implement ListView with CheckBox, modified from the post "Custom ListView with ImageView".



At the beginning, I tried to implement OnCheckedChangeListener for the CheckBox; to handle the check state. But, it will be called when the ListView item scroll-out from the screen, and clear the check state unexpectedly.

Finally, I implement OnClickListener. It work as expected.


/res/layout/row.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal">

    <CheckBox
        android:id="@+id/rowCheckBox"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

    <ImageView
        android:id="@+id/rowImageView"
        android:layout_gravity="center"
        android:layout_width="48dp"
        android:layout_height="48dp" />

    <TextView
        android:id="@+id/rowTextView"
        android:layout_gravity="center"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</LinearLayout>


/res/layout/activity_main.xml
<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"
    tools:context="com.blogspot.android_er.androidcheckboxlistview.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" />
    <Button
        android:id="@+id/lookup"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Look up"/>
    <ListView
        android:id="@+id/listview"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

</LinearLayout>



MainActivity.java
package com.blogspot.android_er.androidcheckboxlistview;

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

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

public class MainActivity extends AppCompatActivity {

    public class Item {
        boolean checked;
        Drawable ItemDrawable;
        String ItemString;
        Item(Drawable drawable, String t, boolean b){
            ItemDrawable = drawable;
            ItemString = t;
            checked = b;
        }

        public boolean isChecked(){
            return checked;
        }
    }

    static class ViewHolder {
        CheckBox checkBox;
        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;
        }

        public boolean isChecked(int position) {
            return list.get(position).checked;
        }

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

            // reuse views
            ViewHolder viewHolder = new ViewHolder();
            if (rowView == null) {
                LayoutInflater inflater = ((Activity) context).getLayoutInflater();
                rowView = inflater.inflate(R.layout.row, null);

                viewHolder.checkBox = (CheckBox) rowView.findViewById(R.id.rowCheckBox);
                viewHolder.icon = (ImageView) rowView.findViewById(R.id.rowImageView);
                viewHolder.text = (TextView) rowView.findViewById(R.id.rowTextView);
                rowView.setTag(viewHolder);
            } else {
                viewHolder = (ViewHolder) rowView.getTag();
            }

            viewHolder.icon.setImageDrawable(list.get(position).ItemDrawable);
            viewHolder.checkBox.setChecked(list.get(position).checked);

            final String itemStr = list.get(position).ItemString;
            viewHolder.text.setText(itemStr);

            viewHolder.checkBox.setTag(position);

            /*
            viewHolder.checkBox.setOnCheckedChangeListener(
                    new CompoundButton.OnCheckedChangeListener() {
                @Override
                public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
                    list.get(position).checked = b;

                    Toast.makeText(getApplicationContext(),
                            itemStr + "onCheckedChanged\nchecked: " + b,
                            Toast.LENGTH_LONG).show();
                }
            });
            */

            viewHolder.checkBox.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    boolean newState = !list.get(position).isChecked();
                    list.get(position).checked = newState;
                    Toast.makeText(getApplicationContext(),
                            itemStr + "setOnClickListener\nchecked: " + newState,
                            Toast.LENGTH_LONG).show();
                }
            });

            viewHolder.checkBox.setChecked(isChecked(position));

            return rowView;
        }
    }

    Button btnLookup;
    List<Item> items;
    ListView listView;
    ItemsListAdapter myItemsListAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        listView = (ListView)findViewById(R.id.listview);
        btnLookup = (Button)findViewById(R.id.lookup);

        initItems();
        myItemsListAdapter = new ItemsListAdapter(this, items);
        listView.setAdapter(myItemsListAdapter);

        listView.setOnItemClickListener(new AdapterView.OnItemClickListener(){

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

        btnLookup.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                String str = "Check items:\n";

                for (int i=0; i<items.size(); i++){
                    if (items.get(i).isChecked()){
                        str += i + "\n";
                    }
                }

                /*
                int cnt = myItemsListAdapter.getCount();
                for (int i=0; i<cnt; i++){
                    if(myItemsListAdapter.isChecked(i)){
                        str += i + "\n";
                    }
                }
                */

                Toast.makeText(MainActivity.this,
                        str,
                        Toast.LENGTH_LONG).show();

            }
        });
    }

    private void initItems(){
        items = 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);
            boolean b = false;
            Item item = new Item(d, s, b);
            items.add(item);
        }

        arrayDrawable.recycle();
        arrayText.recycle();
    }

}



/res/values/arrays.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <array name="resicon">
        <item>@android:drawable/ic_dialog_alert</item>
        <item>@android:drawable/ic_dialog_dialer</item>
        <item>@android:drawable/ic_dialog_email</item>
        <item>@android:drawable/ic_dialog_info</item>
        <item>@android:drawable/ic_dialog_map</item>
        <item>@android:drawable/ic_menu_camera</item>
        <item>@android:drawable/ic_menu_compass</item>
        <item>@android:drawable/ic_menu_gallery</item>
        <item>@android:drawable/ic_menu_my_calendar</item>
        <item>@android:drawable/ic_menu_myplaces</item>
        <item>@android:drawable/ic_menu_slideshow</item>
        <item>@android:drawable/ic_menu_today</item>
    </array>
    <array name="restext">
        <item>"alert"</item>
        <item>"dialer"</item>
        <item>"email"</item>
        <item>"info"</item>
        <item>"map"</item>
        <item>"camera"</item>
        <item>"compass"</item>
        <item>"gallery"</item>
        <item>"calendar"</item>
        <item>"myplaces"</item>
        <item>"slideshow"</item>
        <item>"today"</item>
    </array>

</resources>



Thursday, May 26, 2016

Load WebP from Internet and display in ListView


WebP is a modern image format that provides superior lossless and lossy compression for images on the web. Details refer Google Developers - WebP.

WebP is supported starting from Android 4.0+ (reference: Android Developers - Supported Media Formats). This example modify from the post "Async load image from internet to ListView" to load WebP from internet and display in ListView. Once item clicked, use "Simplest way to open browser using CustomTabsIntent.Builder".


To use CustomTabsIntent.Builder in our app, To use CustomTabsIntent.Builder, edit app/build.gradle to add dependencies of compile 'com.android.support:customtabs:23.0.0'.

The WebP images load from the page Google Developers - WebP Image Galleries.

MainActivity.java
package com.blogspot.android_er.androidimage;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.customtabs.CustomTabsIntent;
import android.support.v7.app.AppCompatActivity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.WeakReference;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.Arrays;

public class MainActivity extends AppCompatActivity {

    final static String src[] = {
            "https://www.gstatic.com/webp/gallery3/1_webp_ll.webp",
            "https://www.gstatic.com/webp/gallery3/1_webp_a.webp",
            "https://www.gstatic.com/webp/gallery3/2_webp_ll.webp",
            "https://www.gstatic.com/webp/gallery3/2_webp_a.webp",
            "https://www.gstatic.com/webp/gallery3/3_webp_ll.webp",
            "https://www.gstatic.com/webp/gallery3/3_webp_a.webp",
            "https://www.gstatic.com/webp/gallery3/4_webp_ll.webp",
            "https://www.gstatic.com/webp/gallery3/4_webp_a.webp",
            "https://www.gstatic.com/webp/gallery3/5_webp_ll.webp",
            "https://www.gstatic.com/webp/gallery3/5_webp_a.webp" };

    ListView imageList;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        imageList = (ListView) findViewById(R.id.imagelist);
        ArrayList<String> srcList = new ArrayList<String>(Arrays.asList(src));
        imageList.setAdapter(new CustomListAdapter(this, srcList));

        imageList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                String imageSrc = src[position];
                Toast.makeText(MainActivity.this,
                        imageSrc,
                        Toast.LENGTH_LONG).show();

                Uri imageUri = Uri.parse(imageSrc);
                new CustomTabsIntent.Builder()
                        .build()
                        .launchUrl(MainActivity.this, imageUri);
            }
        });
    }

    // ----------------------------------------------------

    public class CustomListAdapter extends BaseAdapter {
        private ArrayList<String> listData;
        private LayoutInflater layoutInflater;

        public CustomListAdapter(Context context, ArrayList<String> listData) {
            this.listData = listData;
            layoutInflater = LayoutInflater.from(context);
        }

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

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

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

        public View getView(int position, View convertView, ViewGroup parent) {
            ViewHolder holder;
            if (convertView == null) {
                convertView = layoutInflater.inflate(R.layout.row, null);
                holder = new ViewHolder();
                holder.icon = (ImageView)convertView.findViewById(R.id.icon);
                holder.text = (TextView)convertView.findViewById(R.id.text);
                convertView.setTag(holder);
            } else {
                holder = (ViewHolder) convertView.getTag();
            }

            holder.text.setText(
                    String.valueOf(position) + "\n" + src[position]);

            if (holder.icon != null) {
                new BitmapWorkerTask(holder.icon).execute(listData.get(position));
            }
            return convertView;
        }

        class ViewHolder {
            ImageView icon;
            TextView text;
        }
    }

    // ----------------------------------------------------
    // Load bitmap in AsyncTask
    // ref:
    // http://developer.android.com/training/displaying-bitmaps/process-bitmap.html
    class BitmapWorkerTask extends AsyncTask<String, Void, Bitmap> {
        private final WeakReference<ImageView> imageViewReference;
        private String imageUrl;

        public BitmapWorkerTask(ImageView imageView) {
            // Use a WeakReference to ensure the ImageView can be garbage
            // collected
            imageViewReference = new WeakReference<ImageView>(imageView);
        }

        // Decode image in background.
        @Override
        protected Bitmap doInBackground(String... params) {
            imageUrl = params[0];
            return LoadImage(imageUrl);
        }

        // Once complete, see if ImageView is still around and set bitmap.
        @Override
        protected void onPostExecute(Bitmap bitmap) {
            if (imageViewReference != null && bitmap != null) {
                final ImageView imageView = imageViewReference.get();
                if (imageView != null) {
                    imageView.setImageBitmap(bitmap);
                }
            }
        }

        private Bitmap LoadImage(String URL) {
            Bitmap bitmap = null;
            InputStream in = null;
            try {
                in = OpenHttpConnection(URL);
                bitmap = BitmapFactory.decodeStream(in);
                in.close();
            } catch (IOException e1) {
            }
            return bitmap;
        }

        private InputStream OpenHttpConnection(String strURL)
                throws IOException {
            InputStream inputStream = null;
            URL url = new URL(strURL);
            URLConnection conn = url.openConnection();

            try {
                HttpURLConnection httpConn = (HttpURLConnection) conn;
                httpConn.setRequestMethod("GET");
                httpConn.connect();

                if (httpConn.getResponseCode() == HttpURLConnection.HTTP_OK) {
                    inputStream = httpConn.getInputStream();
                }
            } catch (Exception ex) {
            }
            return inputStream;
        }
    }
}


layout/row.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ImageView
        android:id="@+id/icon"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <TextView
        android:id="@+id/text"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

</LinearLayout>

layout/activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<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:padding="16dp"
    android:orientation="vertical"
    tools:context="com.blogspot.android_er.androidimage.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" />

    <ListView
        android:id="@+id/imagelist"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" />
</LinearLayout>


uses-permission of "android.permission.INTERNET" is needed in AndroidManifest.xml

download filesDownload the files .

Wednesday, April 22, 2015

Async load image from internet to ListView

Android example to load images in AsyncTask from internet to ListView.


MainActivity.java
package com.example.androidasynclist;

import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.WeakReference;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.Arrays;

import android.support.v7.app.ActionBarActivity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;

public class MainActivity extends ActionBarActivity {

 final static String src[] = {
   "https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh45-l11b9CxlWURRdH3KtwaQYMf7lvCjGjhbao52Wi5r7qrd0Xfth6xTflusBxKTwJe8172h0klxldaYUJESZzyz5prDEKN2dtHrH4IaD-9OTdx1CSkein7e0FMVFBv4WVw4COAQx5vD4/s1600/_01.png",
   "https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEggAIxdysN9SF1x7kU-8qHa3-ut75IlMneUrZj008Rnw1uZoRt8cEc08GNuBOrH1oYvERfoGKANoo1GVVAEQMOcYUt3THG0WJXl0nUyv1pYyot_fLYTfBpOvIU4LgKrRdqKbcjNpDAqZjk/s1600/_02.png",
   "https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEicQXPrH8ePv6XTHC-gVrwt5IODdKqiaoZUiJpDZBOeKbKt1zS1deLLOIdpxLYCXCnuXTIP2ZaCFsLY49sDOmda6-S6kHJBaCrbzNlsXornSIPOW3J__TaAYj4mN6kniZIHnKlOD7XSRzE/s1600/_03.png",
   "https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibJPrKh6gadVz_Lk9WB88l2h1eFjXzwzltzT3qawdhx-whIker16zNLjjdOlZK6ZQb-g-Gh8f6KQgKNz3LEM6lV_uTfRjB_Jqyijx0UhXCDiBk2PmGeG9JepX3SKtG9smYIgCxoz6YBcg/s1600/_04.png",
   "https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgJYw1j_8u6OyPr-X5kxKghanaf4uZgWykHGnR4T82FJ8X8KeVcZFT91aNR-mcUKYh8_VW4g6bC_VwskODH9yEu4Q3S_0bdtzx7fixquKWv0BVJGILN-b0vpvXGerWTPf-H6xqtmHPAq74/s1600/_05.png",
   "https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEisebiSsu0boJ3EncEPMYnLj8MEvb2amGp0W4jrvTz-htJos8CHlUjtqALhC3Z1tS73zY1cKDn14WDJ0qqsIEova5rGxtKqfGw4jaPAWpUpWlM7OWrQrTthmZuXDlvONPUP_ixqypr1R5Y/s1600/_06.png",
   "https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgxZwuI5jNXioK2PBfvFkhcyNj-qGTmnB8_pXATaGl5VwKWitoWAbe_OecmK-LimzJ95x_YmYjgrOY2xCLr9ScwzOalPC_1wx1l3rWvN-SKkYinS-LjQoei6OiuCA5Vhqz5XjEwrCfFv4A/s1600/_07.png",
   "https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhN_NWFc1tGg7yOlyj_ytqlzlAeUyjL-EOehYIKwpjqIZFdpiFxFK292j5Nl2Nercsb0JVcMGk0BNJ_7DwShmOhzbtAOreQBxXV5Kf-PnxizNC-g-relCv2ojBgAHJHIRG_kE0-B1xVx2I/s1600/_08.png",
   "https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhvnZ4Mucl5g31ikF1BFvcPP4L2ligLXcw71xjpTIgpgbw9ycf0kGWC_dE6asoXoQq4BOY-mdKQoe6dCUpTca5jMM2BBTjigDqbvvePkhx4hPkmHvhm7HlgYj5UMGZHmBbSCrleitJ2ekQ/s1600/_09.png",
   "https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjM-Pv79aw3p7_5zjgN08vWs6_qx7QHGxVX9kofXoAoShjrURoMNk10AgH5intycrEB6o4nb215IqkeAUGjo7A8aBRFUe_052Vmn5cY7rIYyaxFCVbeJTADl0lYj4kD71t2psHKYAsk3Uw/s1600/_10.png",
   "https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiQAPsubpaTgVDk1vkG8Ktml3nljEBbRfva7J3hqQ1QfJZ1wdKp9UIbm8-JNyCeHwmPFEGpZ5GEih6Zgn9giK3Gcfbka8Sbqfj-0VqvCUzu7w3JbZ6QTMwGmf10zil_xeDz0p6zPopN0nY/s1600/_11.png",
   "https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEidlI97E_km-6-Yx-xqrccSG5TNH5e_RU-NTOesxP1SCQMMf2ft1TQrwIA8MnapXjPrLDuzaJDzD4Eni11C7dqTJAY37LympC128pGE0OyBSZzRhyphenhyphenPYxovNdmI_JgP8l0B5dVcoK_txhy4/s1600/_12.png" };

 ListView imageList;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);

  imageList = (ListView) findViewById(R.id.imagelist);
  ArrayList<String> srcList = new ArrayList<String>(Arrays.asList(src));
  imageList.setAdapter(new CustomListAdapter(this, srcList));
 }

 // ----------------------------------------------------

 public class CustomListAdapter extends BaseAdapter {
  private ArrayList<String> listData;
  private LayoutInflater layoutInflater;

  public CustomListAdapter(Context context, ArrayList<String> listData) {
   this.listData = listData;
   layoutInflater = LayoutInflater.from(context);
  }

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

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

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

  public View getView(int position, View convertView, ViewGroup parent) {
   ViewHolder holder;
   if (convertView == null) {
    convertView = layoutInflater.inflate(R.layout.row, null);
    holder = new ViewHolder();
    holder.icon = (ImageView)convertView.findViewById(R.id.icon);
    holder.text = (TextView)convertView.findViewById(R.id.text);
    convertView.setTag(holder);
   } else {
    holder = (ViewHolder) convertView.getTag();
   }
   
   holder.text.setText(String.valueOf(position));

   if (holder.icon != null) {
    new BitmapWorkerTask(holder.icon).execute(listData.get(position));
   }
   return convertView;
  }

  class ViewHolder {
   ImageView icon;
   TextView text;
  }
 }

 // ----------------------------------------------------
 // Load bitmap in AsyncTask
 // ref:
 // http://developer.android.com/training/displaying-bitmaps/process-bitmap.html
 class BitmapWorkerTask extends AsyncTask<String, Void, Bitmap> {
  private final WeakReference<ImageView> imageViewReference;
  private String imageUrl;

  public BitmapWorkerTask(ImageView imageView) {
   // Use a WeakReference to ensure the ImageView can be garbage
   // collected
   imageViewReference = new WeakReference<ImageView>(imageView);
  }

  // Decode image in background.
  @Override
  protected Bitmap doInBackground(String... params) {
   imageUrl = params[0];
   return LoadImage(imageUrl);
  }

  // Once complete, see if ImageView is still around and set bitmap.
  @Override
  protected void onPostExecute(Bitmap bitmap) {
   if (imageViewReference != null && bitmap != null) {
    final ImageView imageView = imageViewReference.get();
    if (imageView != null) {
     imageView.setImageBitmap(bitmap);
    }
   }
  }

  private Bitmap LoadImage(String URL) {
   Bitmap bitmap = null;
   InputStream in = null;
   try {
    in = OpenHttpConnection(URL);
    bitmap = BitmapFactory.decodeStream(in);
    in.close();
   } catch (IOException e1) {
   }
   return bitmap;
  }

  private InputStream OpenHttpConnection(String strURL)
    throws IOException {
   InputStream inputStream = null;
   URL url = new URL(strURL);
   URLConnection conn = url.openConnection();

   try {
    HttpURLConnection httpConn = (HttpURLConnection) conn;
    httpConn.setRequestMethod("GET");
    httpConn.connect();

    if (httpConn.getResponseCode() == HttpURLConnection.HTTP_OK) {
     inputStream = httpConn.getInputStream();
    }
   } catch (Exception ex) {
   }
   return inputStream;
  }
 }
}

/res/layout/activity_main.xml
<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:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.androidasynclist.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" />

    <ListView
        android:id="@+id/imagelist"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" />

</LinearLayout>

/res/layout/row.xml
<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="wrap_content"
    android:orientation="horizontal" >

    <ImageView
        android:id="@+id/icon"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <TextView
        android:id="@+id/text"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

</LinearLayout>

Permission of "android.permission.INTERNET" is needed in AndroidManifest.xml.



download filesDownload the files.

Related:
Load WebP from Internet and display in ListView

Monday, January 19, 2015

Drag and Drop between ListView and GridView

Previous example show how to implement Drag-and-Drop between ListViews. As both ListView and Gridiew subclasses of AbsListView, it's easy to implement Drag-and-Drop between ListView and GridView.


Refactory LinearLayoutListView.java to LinearLayoutAbsListView.java, to implement our custom LinearLayout associate with AbsListView, for ListView or GridView.
package com.example.androidimageviewlist;

import android.content.Context;
import android.util.AttributeSet;
import android.widget.AbsListView;
import android.widget.LinearLayout;

public class LinearLayoutAbsListView extends LinearLayout {
 
 AbsListView absListView;

 public LinearLayoutAbsListView(Context context) {
  super(context);
  // TODO Auto-generated constructor stub
 }

 public LinearLayoutAbsListView(Context context, AttributeSet attrs) {
  super(context, attrs);
  // TODO Auto-generated constructor stub
 }

 public LinearLayoutAbsListView(Context context, AttributeSet attrs,
   int defStyleAttr) {
  super(context, attrs, defStyleAttr);
  // TODO Auto-generated constructor stub
 }

 public void setAbsListView(AbsListView alv){
  absListView = alv;
 }

}

Create /res/layout/gridrow.xml to define row layout for GridView.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="horizontal" >

    <ImageView
        android:id="@+id/gridrowImageView"
        android:layout_gravity="center"
        android:layout_width="48dp"
        android:layout_height="48dp" />

</LinearLayout>

Modify /res/layout/activity_main.xml to include three <com.example.androidimageviewlist.LinearLayoutAbsListView>
<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="0dp"
        android:layout_weight="2"
        android:background="@android:color/background_dark"
        android:orientation="horizontal" >

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

            <ListView
                android:id="@+id/listview1"
                android:layout_width="match_parent"
                android:layout_height="wrap_content" />
        </com.example.androidimageviewlist.LinearLayoutAbsListView>

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

            <ListView
                android:id="@+id/listview2"
                android:layout_width="match_parent"
                android:layout_height="wrap_content" />
        </com.example.androidimageviewlist.LinearLayoutAbsListView>
        
        <com.example.androidimageviewlist.LinearLayoutAbsListView
            android:id="@+id/pane3"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_margin="4dp"
            android:layout_weight="1"
            android:background="@android:color/background_light"
            android:orientation="vertical" >

            <GridView
                android:id="@+id/gridview3"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:numColumns="auto_fit"
                android:verticalSpacing="10dp"
                android:horizontalSpacing="10dp"
                android:columnWidth="60dp"
                android:stretchMode="columnWidth"
                android:gravity="center" />
        </com.example.androidimageviewlist.LinearLayoutAbsListView>
    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:orientation="horizontal" >

        <TextView
            android:id="@+id/prompt"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="@android:color/black"
            android:gravity="bottom"
            android:textColor="@android:color/white" />
    </LinearLayout>

</LinearLayout>

MainActivity.java
package com.example.androidimageviewlist;

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

import android.support.v7.app.ActionBarActivity;
import android.text.method.ScrollingMovementMethod;
import android.app.Activity;
import android.content.ClipData;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.view.DragEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.DragShadowBuilder;
import android.view.View.OnDragListener;
import android.view.View.OnLongClickListener;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.BaseAdapter;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends ActionBarActivity {

 //items stored in ListView
 public class Item {
  Drawable ItemDrawable;
  String ItemString;
  Item(Drawable drawable, String t){
   ItemDrawable = drawable;
   ItemString = t;
  }
 }
 
 //objects passed in Drag and Drop operation
 class PassObject{
  View view;
  Item item;
  List<Item> srcList;
  
  PassObject(View v, Item i, List<Item> s){
   view = v;
   item = i;
   srcList = s;
  }
 }
 
 static class ViewHolder {
  ImageView icon;
  TextView text; 
 }
 
 static class GridViewHolder {
  ImageView icon; 
 }
 
 public class ItemBaseAdapter extends BaseAdapter {

  Context context;
  List<Item> list;

  ItemBaseAdapter(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;
  }
  
  public List<Item> getList(){
   return list;
  }

  @Override
  public View getView(int position, View convertView, ViewGroup parent) {
   // TODO Auto-generated method stub
   return null;
  }
  
 }
 

 public class ItemListAdapter extends ItemBaseAdapter {
  
  ItemListAdapter(Context c, List<Item> l) {
   super(c, l);
  }

  @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);
      
      rowView.setOnDragListener(new ItemOnDragListener(list.get(position)));

      return rowView;
  }

 }
 
 public class ItemGridAdapter extends ItemBaseAdapter {

  ItemGridAdapter(Context c, List<Item> l) {
   super(c, l);
  }
  
  @Override
  public View getView(int position, View convertView, ViewGroup parent) {
   View gridrowView = convertView;
   
      // reuse views
      if (gridrowView == null) {
       LayoutInflater inflater = ((Activity) context).getLayoutInflater();
       gridrowView = inflater.inflate(R.layout.gridrow, null);

       GridViewHolder gridviewHolder = new GridViewHolder();
       gridviewHolder.icon = (ImageView) gridrowView.findViewById(R.id.gridrowImageView);
       gridrowView.setTag(gridviewHolder); 
      }

      GridViewHolder holder = (GridViewHolder) gridrowView.getTag();
      holder.icon.setImageDrawable(list.get(position).ItemDrawable);

      gridrowView.setOnDragListener(new ItemOnDragListener(list.get(position)));

      return gridrowView;
  }
  
 }

 List<Item> items1, items2, items3;
 ListView listView1, listView2;
 GridView gridView3;
 ItemListAdapter myItemListAdapter1, myItemListAdapter2;
 ItemGridAdapter myItemGridAdapter3;
 LinearLayoutAbsListView area1, area2, area3;
 TextView prompt;
 
 //Used to resume original color in drop ended/exited
 int resumeColor;

 @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);
  gridView3 = (GridView)findViewById(R.id.gridview3);
  
  area1 = (LinearLayoutAbsListView)findViewById(R.id.pane1);
  area2 = (LinearLayoutAbsListView)findViewById(R.id.pane2);
  area3 = (LinearLayoutAbsListView)findViewById(R.id.pane3);
  area1.setOnDragListener(myOnDragListener);
  area2.setOnDragListener(myOnDragListener);
  area3.setOnDragListener(myOnDragListener);
  area1.setAbsListView(listView1);
  area2.setAbsListView(listView2);
  area3.setAbsListView(gridView3);
  
  initItems();
  myItemListAdapter1 = new ItemListAdapter(this, items1);
  myItemListAdapter2 = new ItemListAdapter(this, items2);
  myItemGridAdapter3 = new ItemGridAdapter(this, items3);
  listView1.setAdapter(myItemListAdapter1);
  listView2.setAdapter(myItemListAdapter2);
  gridView3.setAdapter(myItemGridAdapter3);
  
  listView1.setOnItemClickListener(listOnItemClickListener);
  listView2.setOnItemClickListener(listOnItemClickListener);
  gridView3.setOnItemClickListener(listOnItemClickListener);
  
  listView1.setOnItemLongClickListener(myOnItemLongClickListener);
  listView2.setOnItemLongClickListener(myOnItemLongClickListener);
  gridView3.setOnItemLongClickListener(myOnItemLongClickListener);
  
  prompt = (TextView) findViewById(R.id.prompt);
  // make TextView scrollable
  prompt.setMovementMethod(new ScrollingMovementMethod());
  //clear prompt area if LongClick
  prompt.setOnLongClickListener(new OnLongClickListener(){
   
   @Override
   public boolean onLongClick(View v) {
    prompt.setText("");
    return true; 
   }});
  
  resumeColor  = getResources().getColor(android.R.color.background_light);

 }
 
 OnItemLongClickListener myOnItemLongClickListener = new OnItemLongClickListener(){

  @Override
  public boolean onItemLongClick(AdapterView<?> parent, View view,
    int position, long id) {
   Item selectedItem = (Item)(parent.getItemAtPosition(position));
   
   ItemBaseAdapter associatedAdapter = (ItemBaseAdapter)(parent.getAdapter());
      List<Item> associatedList = associatedAdapter.getList();
   
   PassObject passObj = new PassObject(view, selectedItem, associatedList);

   ClipData data = ClipData.newPlainText("", "");
   DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(view);
   view.startDrag(data, shadowBuilder, passObj, 0);
   
   return true;
  }
  
 };
 
 OnDragListener myOnDragListener = new OnDragListener() {

  @Override
  public boolean onDrag(View v, DragEvent event) {
   String area;
   if(v == area1){
    area = "area1"; 
   }else if(v == area2){
    area = "area2"; 
   }else if(v == area3){
    area = "area3"; 
   }else{
    area = "unknown"; 
   }
   
   switch (event.getAction()) {
    case DragEvent.ACTION_DRAG_STARTED:
     prompt.append("ACTION_DRAG_STARTED: " + area  + "\n");
     break; 
    case DragEvent.ACTION_DRAG_ENTERED:
     prompt.append("ACTION_DRAG_ENTERED: " + area  + "\n");
     break; 
    case DragEvent.ACTION_DRAG_EXITED:
     prompt.append("ACTION_DRAG_EXITED: " + area  + "\n");
     break; 
    case DragEvent.ACTION_DROP:
     prompt.append("ACTION_DROP: " + area  + "\n");

     PassObject passObj = (PassObject)event.getLocalState();
     View view = passObj.view;
     Item passedItem = passObj.item;
     List<Item> srcList = passObj.srcList;
     AbsListView oldParent = (AbsListView)view.getParent();
     ItemBaseAdapter srcAdapter = (ItemBaseAdapter)(oldParent.getAdapter());
     
     LinearLayoutAbsListView newParent = (LinearLayoutAbsListView)v;
     ItemBaseAdapter destAdapter = (ItemBaseAdapter)(newParent.absListView.getAdapter());
        List<Item> destList = destAdapter.getList();
     
     if(removeItemToList(srcList, passedItem)){
      addItemToList(destList, passedItem);
     }
     
     srcAdapter.notifyDataSetChanged();
     destAdapter.notifyDataSetChanged();
     
     //smooth scroll to bottom
     newParent.absListView.smoothScrollToPosition(destAdapter.getCount()-1);
     
     break;
      case DragEvent.ACTION_DRAG_ENDED:
       prompt.append("ACTION_DRAG_ENDED: " + area  + "\n");  
      default:
       break;    
   }
      
   return true;
  }
  
 };
 
 class ItemOnDragListener implements OnDragListener{
  
  Item  me;
  
  ItemOnDragListener(Item i){
   me = i;
  }

  @Override
  public boolean onDrag(View v, DragEvent event) {
   switch (event.getAction()) {
   case DragEvent.ACTION_DRAG_STARTED:
    prompt.append("Item ACTION_DRAG_STARTED: " + "\n");
    break; 
   case DragEvent.ACTION_DRAG_ENTERED:
    prompt.append("Item ACTION_DRAG_ENTERED: " + "\n");
    v.setBackgroundColor(0x30000000);
    break; 
   case DragEvent.ACTION_DRAG_EXITED:
    prompt.append("Item ACTION_DRAG_EXITED: " + "\n");
    v.setBackgroundColor(resumeColor);
    break; 
   case DragEvent.ACTION_DROP:
    prompt.append("Item ACTION_DROP: " + "\n");

    PassObject passObj = (PassObject)event.getLocalState();
    View view = passObj.view;
    Item passedItem = passObj.item;
    List<Item> srcList = passObj.srcList;
    AbsListView oldParent = (AbsListView)view.getParent();
    ItemBaseAdapter srcAdapter = (ItemBaseAdapter)(oldParent.getAdapter());
    
    AbsListView newParent = (AbsListView)v.getParent();
    ItemBaseAdapter destAdapter = (ItemBaseAdapter)(newParent.getAdapter());
    List<Item> destList = destAdapter.getList();
    
    int removeLocation = srcList.indexOf(passedItem);
    int insertLocation = destList.indexOf(me);
    /*
     * If drag and drop on the same list, same position,
     * ignore
     */
    if(srcList != destList || removeLocation != insertLocation){
     if(removeItemToList(srcList, passedItem)){
      destList.add(insertLocation, passedItem);
     }
     
     srcAdapter.notifyDataSetChanged();
     destAdapter.notifyDataSetChanged();
    }

    v.setBackgroundColor(resumeColor);
    
    break;
     case DragEvent.ACTION_DRAG_ENDED:
      prompt.append("Item ACTION_DRAG_ENDED: "  + "\n");
      v.setBackgroundColor(resumeColor);
     default:
      break;    
  }
     
  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>();
  items3 = 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;
 }

}

download filesDownload the files.

Sunday, January 11, 2015

Improved Drag and Drop items between ListView

Last post show my first try "Drag and Drop items between ListView". The source and destination of the Drag and Drop operation is hard coded and fixed. It's too un-flexible! It is improved here to provide more flexible approach.


In order to get the associated ListView from any LinearLayout to be drop, I create a new class LinearLayoutListView extends LinearLayout, associated with a ListView.

LinearLayoutListView.java
package com.example.androidimageviewlist;

import android.content.Context;
import android.util.AttributeSet;
import android.widget.LinearLayout;
import android.widget.ListView;

public class LinearLayoutListView extends LinearLayout {
 
 ListView listView;

 public LinearLayoutListView(Context context) {
  super(context);
  // TODO Auto-generated constructor stub
 }

 public LinearLayoutListView(Context context, AttributeSet attrs) {
  super(context, attrs);
  // TODO Auto-generated constructor stub
 }

 public LinearLayoutListView(Context context, AttributeSet attrs,
   int defStyleAttr) {
  super(context, attrs, defStyleAttr);
  // TODO Auto-generated constructor stub
 }

 public void setListView(ListView lv){
  listView = lv;
 }

}

Modify /res/layout/activity_main.xml, to use <com.example.androidimageviewlist.LinearLayoutListView>. And also display three to show the flexibility of the new approach.
<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="0dp"
        android:layout_weight="2"
        android:background="@android:color/background_dark"
        android:orientation="horizontal" >

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

            <ListView
                android:id="@+id/listview1"
                android:layout_width="match_parent"
                android:layout_height="wrap_content" />
        </com.example.androidimageviewlist.LinearLayoutListView>

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

            <ListView
                android:id="@+id/listview2"
                android:layout_width="match_parent"
                android:layout_height="wrap_content" />
        </com.example.androidimageviewlist.LinearLayoutListView>
        
        <com.example.androidimageviewlist.LinearLayoutListView
            android:id="@+id/pane3"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_margin="4dp"
            android:layout_weight="1"
            android:background="@android:color/background_light"
            android:orientation="vertical" >

            <ListView
                android:id="@+id/listview3"
                android:layout_width="match_parent"
                android:layout_height="wrap_content" />
        </com.example.androidimageviewlist.LinearLayoutListView>
    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:orientation="horizontal" >

        <TextView
            android:id="@+id/prompt"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="@android:color/black"
            android:gravity="bottom"
            android:textColor="@android:color/white" />
    </LinearLayout>

</LinearLayout>

MainActivity.java
package com.example.androidimageviewlist;

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

import android.support.v7.app.ActionBarActivity;
import android.text.method.ScrollingMovementMethod;
import android.app.Activity;
import android.content.ClipData;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.view.DragEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.DragShadowBuilder;
import android.view.View.OnDragListener;
import android.view.View.OnLongClickListener;
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 {

 //items stored in ListView
 public class Item {
  Drawable ItemDrawable;
  String ItemString;
  Item(Drawable drawable, String t){
   ItemDrawable = drawable;
   ItemString = t;
  }
 }
 
 //objects passed in Drag and Drop operation
 class PassObject{
  View view;
  Item item;
  List<Item> srcList;
  
  PassObject(View v, Item i, List<Item> s){
   view = v;
   item = i;
   srcList = s;
  }
 }
 
 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, items3;
 ListView listView1, listView2, listView3;
 ItemsListAdapter myItemsListAdapter1, myItemsListAdapter2, myItemsListAdapter3;
 LinearLayoutListView area1, area2, area3;
 TextView prompt;

 @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);
  listView3 = (ListView)findViewById(R.id.listview3);
  
  area1 = (LinearLayoutListView)findViewById(R.id.pane1);
  area2 = (LinearLayoutListView)findViewById(R.id.pane2);
  area3 = (LinearLayoutListView)findViewById(R.id.pane3);
  area1.setOnDragListener(myOnDragListener);
  area2.setOnDragListener(myOnDragListener);
  area3.setOnDragListener(myOnDragListener);
  area1.setListView(listView1);
  area2.setListView(listView2);
  area3.setListView(listView3);
  
  initItems();
  myItemsListAdapter1 = new ItemsListAdapter(this, items1);
  myItemsListAdapter2 = new ItemsListAdapter(this, items2);
  myItemsListAdapter3 = new ItemsListAdapter(this, items3);
  listView1.setAdapter(myItemsListAdapter1);
  listView2.setAdapter(myItemsListAdapter2);
  listView3.setAdapter(myItemsListAdapter3);
  
  //Auto scroll to end of ListView
  listView1.setTranscriptMode(ListView.TRANSCRIPT_MODE_ALWAYS_SCROLL);
  listView2.setTranscriptMode(ListView.TRANSCRIPT_MODE_ALWAYS_SCROLL);
  listView3.setTranscriptMode(ListView.TRANSCRIPT_MODE_ALWAYS_SCROLL);

  listView1.setOnItemClickListener(listOnItemClickListener);
  listView2.setOnItemClickListener(listOnItemClickListener);
  listView3.setOnItemClickListener(listOnItemClickListener);
  
  listView1.setOnItemLongClickListener(myOnItemLongClickListener);
  listView2.setOnItemLongClickListener(myOnItemLongClickListener);
  listView3.setOnItemLongClickListener(myOnItemLongClickListener);
  
  prompt = (TextView) findViewById(R.id.prompt);
  // make TextView scrollable
  prompt.setMovementMethod(new ScrollingMovementMethod());
  //clear prompt area if LongClick
  prompt.setOnLongClickListener(new OnLongClickListener(){
   
   @Override
   public boolean onLongClick(View v) {
    prompt.setText("");
    return true; 
   }});

 }
 
 OnItemLongClickListener myOnItemLongClickListener = 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();
   
   PassObject passObj = new PassObject(view, selectedItem, associatedList);
   
   
   ClipData data = ClipData.newPlainText("", "");
   DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(view);
   view.startDrag(data, shadowBuilder, passObj, 0);
   
   return true;
  }
  
 };
 
 OnDragListener myOnDragListener = new OnDragListener() {

  @Override
  public boolean onDrag(View v, DragEvent event) {
   String area;
   if(v == area1){
    area = "area1"; 
   }else if(v == area2){
    area = "area2"; 
   }else if(v == area3){
    area = "area3"; 
   }else{
    area = "unknown"; 
   }
   
   switch (event.getAction()) {
    case DragEvent.ACTION_DRAG_STARTED:
     prompt.append("ACTION_DRAG_STARTED: " + area  + "\n");
     break; 
    case DragEvent.ACTION_DRAG_ENTERED:
     prompt.append("ACTION_DRAG_ENTERED: " + area  + "\n");
     break; 
    case DragEvent.ACTION_DRAG_EXITED:
     prompt.append("ACTION_DRAG_EXITED: " + area  + "\n");
     break; 
    case DragEvent.ACTION_DROP:
     prompt.append("ACTION_DROP: " + area  + "\n");

     PassObject passObj = (PassObject)event.getLocalState();
     View view = passObj.view;
     Item passedItem = passObj.item;
     List<Item> srcList = passObj.srcList;
     ListView oldParent = (ListView)view.getParent();
     ItemsListAdapter srcAdapter = (ItemsListAdapter)(oldParent.getAdapter());
     
     LinearLayoutListView newParent = (LinearLayoutListView)v;
     ItemsListAdapter destAdapter = (ItemsListAdapter)(newParent.listView.getAdapter());
        List<Item> destList = destAdapter.getList();
     
     if(removeItemToList(srcList, passedItem)){
      addItemToList(destList, passedItem);
     }
     
     srcAdapter.notifyDataSetChanged();
     destAdapter.notifyDataSetChanged();
     
     break;
      case DragEvent.ACTION_DRAG_ENDED:
       prompt.append("ACTION_DRAG_ENDED: " + area  + "\n");   
      default:
       break;    
   }
      
   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>();
  items3 = 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;
 }

}

/res/layout/row.xml and /res/values/arrays.xml, refer to previous post of "Custom ListView with ImageView".

To use Drag and Drop on your app, you have to modify AndroidManifest.xml to set android:minSdkVersion="11".

download filesDownload the files.


In this exercise, it drag a ListView item, drop on a LinearLayout, then add the item to the associated ListView, always on bottom. Not drop on ListView actually.

In this exercise, "Drag and Drop items between ListView, with OnDragListener on ListView cells", another OnDragListener (ItemOnDragListener) implemented for rowView of ListView items, such that we can actually drop on ListView items, and insert in the previous position.

Drag and Drop items between ListView

This example show how to move items between ListView by Drag and Drop. (I don't know any standard method to achieve this, it's my own implementation)


MainActivity.java
package com.example.androidimageviewlist;

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

import android.support.v7.app.ActionBarActivity;
import android.text.method.ScrollingMovementMethod;
import android.app.Activity;
import android.content.ClipData;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.view.DragEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.DragShadowBuilder;
import android.view.View.OnDragListener;
import android.view.View.OnLongClickListener;
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.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends ActionBarActivity {
 
 //items stored in ListView
 public class Item {
  Drawable ItemDrawable;
  String ItemString;
  Item(Drawable drawable, String t){
   ItemDrawable = drawable;
   ItemString = t;
  }
 }
 
 //objects passed in Drag and Drop operation
 class PassObject{
  View view;
  Item item;
  
  PassObject(View v, Item i){
   view = v;
   item = i;
  }
 }
 
 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;
 LinearLayout area1, area2;
 TextView prompt;

 @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);
  
  area1 = (LinearLayout)findViewById(R.id.pane1);
  area2 = (LinearLayout)findViewById(R.id.pane2);
  area1.setOnDragListener(myOnDragListener);
  area2.setOnDragListener(myOnDragListener);
  
  initItems();
  myItemsListAdapter1 = new ItemsListAdapter(this, items1);
  myItemsListAdapter2 = new ItemsListAdapter(this, items2);
  listView1.setAdapter(myItemsListAdapter1);
  listView2.setAdapter(myItemsListAdapter2);
  
  //Auto scroll to end of ListView
  listView1.setTranscriptMode(ListView.TRANSCRIPT_MODE_ALWAYS_SCROLL);
  listView2.setTranscriptMode(ListView.TRANSCRIPT_MODE_ALWAYS_SCROLL);

  listView1.setOnItemClickListener(listOnItemClickListener);
  listView2.setOnItemClickListener(listOnItemClickListener);
  
  listView1.setOnItemLongClickListener(myOnItemLongClickListener);
  listView2.setOnItemLongClickListener(myOnItemLongClickListener);
  
  prompt = (TextView) findViewById(R.id.prompt);
  // make TextView scrollable
  prompt.setMovementMethod(new ScrollingMovementMethod());
  //clear prompt area if LongClick
  prompt.setOnLongClickListener(new OnLongClickListener(){
   
   @Override
   public boolean onLongClick(View v) {
    prompt.setText("");
    return true; 
   }});

 }
 OnItemLongClickListener myOnItemLongClickListener = new OnItemLongClickListener(){

  @Override
  public boolean onItemLongClick(AdapterView<?> parent, View view,
    int position, long id) {
   Item selectedItem = (Item)(parent.getItemAtPosition(position));
   PassObject passObj = new PassObject(view, selectedItem);
   
   
   ClipData data = ClipData.newPlainText("", "");
   DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(view);
   view.startDrag(data, shadowBuilder, passObj, 0);
   
   return true;
  }
  
 };
 
 OnDragListener myOnDragListener = new OnDragListener() {

  @Override
  public boolean onDrag(View v, DragEvent event) {
   String area;
   if(v == area1){
    area = "area1"; 
   }else if(v == area2){
    area = "area2"; 
   }else{
    area = "unknown"; 
   }
   
   switch (event.getAction()) {
    case DragEvent.ACTION_DRAG_STARTED:
     prompt.append("ACTION_DRAG_STARTED: " + area  + "\n");
     break; 
    case DragEvent.ACTION_DRAG_ENTERED:
     prompt.append("ACTION_DRAG_ENTERED: " + area  + "\n");
     break; 
    case DragEvent.ACTION_DRAG_EXITED:
     prompt.append("ACTION_DRAG_EXITED: " + area  + "\n");
     break; 
    case DragEvent.ACTION_DROP:
     prompt.append("ACTION_DROP: " + area  + "\n");

     PassObject passObj = (PassObject)event.getLocalState();
     View view = passObj.view;
     Item passedItem = passObj.item;
     ListView oldParent = (ListView)view.getParent();
     LinearLayout newParent = (LinearLayout)v;
     
     if(oldParent.equals(listView1)){
      prompt.append("Drag source: listView1" + "\n");
      
      if(newParent.equals(area2)){
       prompt.append("Drop target: area2" + "\n");
       
       if(removeItemToList(items1, passedItem)){
        addItemToList(items2, passedItem); 
       }
       myItemsListAdapter1.notifyDataSetChanged();
       myItemsListAdapter2.notifyDataSetChanged();
       
      }else{
       prompt.append("Invalid Drop target" + "\n");
      }
      
     }else if(oldParent.equals(listView2)){
      prompt.append("Drag source: listView2" + "\n");
      
      if(newParent.equals(area1)){
       prompt.append("Drop target: area1" + "\n");
       
       if(removeItemToList(items2, passedItem)){
        addItemToList(items1, passedItem); 
       }
       myItemsListAdapter1.notifyDataSetChanged();
       myItemsListAdapter2.notifyDataSetChanged();
      }else{
       prompt.append("Invalid Drop target" + "\n");
      }
      
     }else{
      prompt.append("Invalid Drag source: unknown" + "\n");
     }
     break;
      case DragEvent.ACTION_DRAG_ENDED:
       prompt.append("ACTION_DRAG_ENDED: " + area  + "\n");   
      default:
       break;    
   }
      
   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;
 }

}

/res/layout/activity_main.xml
<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="0dp"
        android:layout_weight="2"
        android:background="@android:color/background_dark"
        android:orientation="horizontal" >

        <LinearLayout
            android:id="@+id/pane1"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_margin="4dp"
            android:layout_weight="1"
            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_margin="4dp"
            android:layout_weight="1"
            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
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:orientation="horizontal" >

        <TextView
            android:id="@+id/prompt"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="@android:color/black"
            android:gravity="bottom"
            android:textColor="@android:color/white" />
    </LinearLayout>

</LinearLayout>

/res/layout/row.xml and /res/values/arrays.xml, refer to previous post of "Custom ListView with ImageView".

To use Drag and Drop on your app, you have to modify AndroidManifest.xml to set android:minSdkVersion="11".

download filesDownload the files.


Next:
- It's a too un-flexible approach, The source and destination of the Drag and Drop operation is hard coded and fixed. Next is a "Improved Drag and Drop items between ListView".

- In the exercise "Drag and Drop items between ListView, with OnDragListener on ListView cells", another OnDragListener (ItemOnDragListener) implemented for rowView of ListView items, such that we can actually drop on ListView items, and insert in the previous position.

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.


Thursday, January 8, 2015

Custom ListView with ImageView

It's a custom ListView example, using custom adapter. Each row in the ListView have a ImageView and a TextView.


/res/layout/row.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal" >

    <ImageView
        android:id="@+id/rowImageView"
        android:layout_gravity="center"
        android:layout_width="48dp"
        android:layout_height="48dp" />

    <TextView
        android:id="@+id/rowTextView"
        android:layout_gravity="center"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</LinearLayout>

/res/layout/activity_main.xml
<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:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:orientation="vertical"
    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" />
    <ListView
        android:id="@+id/listview"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

</LinearLayout>

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

 List<Item> items;
 ListView listView;
 ItemsListAdapter myItemsListAdapter;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  listView = (ListView)findViewById(R.id.listview);
  
  initItems();
  myItemsListAdapter = new ItemsListAdapter(this, items);
  listView.setAdapter(myItemsListAdapter);

  listView.setOnItemClickListener(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_LONG).show();
   }});

 }

 private void initItems(){
  items = 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);
   items.add(item);
  }
  
  arrayDrawable.recycle();
  arrayText.recycle();
 }

}

/res/values/arrays.xml, used to load the List.
<?xml version="1.0" encoding="utf-8"?>
<resources>

    <array name="resicon">
        <item>@android:drawable/ic_dialog_alert</item>
        <item>@android:drawable/ic_dialog_dialer</item>
        <item>@android:drawable/ic_dialog_email</item>
        <item>@android:drawable/ic_dialog_info</item>
        <item>@android:drawable/ic_dialog_map</item>
        <item>@android:drawable/ic_menu_camera</item>
        <item>@android:drawable/ic_menu_compass</item>
        <item>@android:drawable/ic_menu_gallery</item>
        <item>@android:drawable/ic_menu_my_calendar</item>
        <item>@android:drawable/ic_menu_myplaces</item>
        <item>@android:drawable/ic_menu_slideshow</item>
        <item>@android:drawable/ic_menu_today</item>
    </array>
    <array name="restext">
        <item>"alert"</item>
        <item>"dialer"</item>
        <item>"email"</item>
        <item>"info"</item>
        <item>"map"</item>
        <item>"camera"</item>
        <item>"compass"</item>
        <item>"gallery"</item>
        <item>"calendar"</item>
        <item>"myplaces"</item>
        <item>"slideshow"</item>
        <item>"today"</item>
    </array>

</resources>

download filesDownload the files.

Next:
Add/Remove items to custom ListView programmatically
Drag and Drop items between ListView
Improved Drag and Drop items between ListView
Drag and Drop items between ListView, with OnDragListener on ListView cells
Drag and Drop between ListView and GridView

Related:
Android ListView with CheckBox