Monday, July 13, 2015

ListView with Custom Adapter

We just created a simple listview using simple ArrayAdapter in the last tutorial which displayed the list of Strings in the vertical list. In this tutorial we will create a listView with a more complex data.



 Our objective for this session is to create a ListView displaying Name of Android Versions along with their versions. Let's begin by planning what our list item will be like.

Above picture shows how each of our ListView item will look like. So let's start by creating a new project with blank Activity.

Then, add the ListView in the layout of Main Activity.


 <RelativeLayout 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:paddingLeft="@dimen/activity_horizontal_margin"  
   android:paddingRight="@dimen/activity_horizontal_margin"  
   android:paddingTop="@dimen/activity_vertical_margin"  
   android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">  
   
   <ListView  
     android:id="@+id/listView"  
     android:layout_width="match_parent"  
     android:layout_height="match_parent"/>  
   
 </RelativeLayout>  
   


Let's define our Model for the list item, Let's create a Java class named AndroidVersion.

 package com.technoguff.listviewexample;  
   

 public class AndroidVersion {  
     
   private String codeName;  
   private String version;  
   private int icon;  
   
   
   public String getCodeName() {  
     return codeName;  
   }  
   
   public void setCodeName(String codeName) {  
     this.codeName = codeName;  
   }  
   
   public String getVersion() {  
     return version;  
   }  
   
   public void setVersion(String version) {  
     this.version = version;  
   }  
   
   public int getIcon() {  
     return icon;  
   }  
   
   public void setIcon(int icon) {  
     this.icon = icon;  
   }  
 }  
   


Then , create a layout for the item view. Create new layout file named layout_item.xml

 <?xml version="1.0" encoding="utf-8"?>  
 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
   android:orientation="vertical" android:layout_width="match_parent"  
   android:layout_height="match_parent">  
   <ImageView  
     android:id="@+id/ivIcon"  
     android:layout_width="64dp"  
     android:layout_height="64dp"   
     android:layout_margin="5dp"/>  
   
   <TextView  
     android:id="@+id/codeName"  
     android:layout_width="wrap_content"  
     android:layout_height="wrap_content"  
     android:layout_toRightOf="@+id/ivIcon"  
     android:textStyle="bold"  
     android:textSize="20sp"  
     />  
   
   <TextView  
     android:id="@+id/version"  
     android:layout_width="wrap_content"  
     android:layout_height="wrap_content"  
     android:layout_toRightOf="@id/ivIcon"  
     android:layout_below="@+id/codeName"  
     />  
   
 </RelativeLayout>  


Now, Create some sample data for our listview by creating an ArrayList of AndroidVersions in MainActivity and create drawable-mdpi folder in res folder of our project. And then place the icons for different versions. GET THE ICONS HERE.


 public class MainActivity extends AppCompatActivity {  
   
   
   
   private ArrayList<AndroidVersion> mVersionList;  
   private ListView mListView;  
   
   @Override  
   protected void onCreate(Bundle savedInstanceState) {  
     super.onCreate(savedInstanceState);  
     setContentView(R.layout.activity_main);  
   
     //Sample Data :: For this tutorial, let's just create sample data in the main activity. In real projects  
     // we will either get the data for our list item from webservices or local storage.  
   
     mVersionList = new ArrayList<AndroidVersion>();  
     AndroidVersion version = new AndroidVersion();  
     version = new AndroidVersion();  
     version.setCodeName("Cupcake");  
     version.setVersion("Android 1.5");  
     version.setIcon(R.drawable.cupcake);  
     mVersionList.add(version);  
   
     version = new AndroidVersion();  
     version.setCodeName("Donut");  
     version.setVersion("Android 1.6");  
     version.setIcon(R.drawable.donut);  
     mVersionList.add(version);  
   
     version = new AndroidVersion();  
     version.setCodeName("Eclair");  
     version.setVersion("Android 2.0");  
     version.setIcon(R.drawable.eclair);  
     mVersionList.add(version);  
   
     version = new AndroidVersion(); 
     version.setCodeName("Froyo");  
     version.setVersion("Android 2.2");  
     version.setIcon(R.drawable.froyo);  
     mVersionList.add(version);  
   
     version = new AndroidVersion();  
     version.setCodeName("Gingerbread");  
     version.setVersion("Android 2.3");  
     version.setIcon(R.drawable.gingerbread);  
     mVersionList.add(version);  
   
 ......  
   
 ......  
   
   


Now, we have the sample data for the list items, we will create our custom adapter class by extending ArrayAdapter and add a constructor..

 package com.technoguff.customadapterexample;  
   
 import android.content.Context;  
 import android.widget.ArrayAdapter;  
   
 import java.util.List;  
   
 /**  
  * Created by darshanz on 7/13/15.  
  */  
 public class CustomAdapter extends ArrayAdapter<AndroidVersion> {  
     
   public CustomAdapter(Context context, int resource, List<AndroidVersion> objects) {  
     super(context, resource, objects);  
   }  
     
 }  


This adapter class will act as a bridge between our data and the list item. Adapter class will do following functions.
1. will use the layout for list item
2.  add data to different views in the item layout.


Before moving forward we need to know that listview will recycle the item layouts when they go out of the screen while scrolling and same layout will be used for other data items.   Since it is expensive to call findViewById() each time the item is displayed in the screen we will use ViewHolder for holding the views in our item layout and reuse them to avoid the overload of find the views from layout.

So the next step is to create a simple ViewHolder class in our Adapter.

 class ViewHolder{  
     ImageView ivIcon;  
     TextView tvCodeName;  
     TextView tvVersion;  
   }  
   


Now let's add a member variable for the List if items that we get from MainActivity, and since we will need to inflate the layout using the getLayoutInflater method form activity let's change our constructor a little so that it has Activity as a parameter.


  private ArrayList<AndroidVersion> mVersionList;  
   private LayoutInflater inflater;  
     
   public CustomAdapter(Activity activity, int resource, ArrayList<AndroidVersion> objects) {  
     super(activity, resource, objects);  
   
     mVersionList = objects;  
     inflater = activity.getLayoutInflater();  
   }  

Now, in order to inflate our layout and set data let's override the getView() method of the LisView and add following code.


 @Override  
   public View getView(int position, View convertView, ViewGroup parent) {  
   
     ViewHolder holder;  
   
   
     if(convertView == null){  
       convertView = inflater.inflate(R.layout.layout_item, null);  
       holder = new ViewHolder();  
       holder.tvCodeName = (TextView)convertView.findViewById(R.id.codeName);  
       holder.tvVersion = (TextView)convertView.findViewById(R.id.version);  
       holder.ivIcon = (ImageView)convertView.findViewById(R.id.ivIcon);  
   
       convertView.setTag(holder);  
   
     }else{  
   
       holder = (ViewHolder)convertView.getTag();  
     }  
   
   
     AndroidVersion version = mVersionList.get(position);  
   
     holder.tvCodeName.setText(version.getCodeName());  
     holder.tvVersion.setText(version.getVersion());  
     holder.ivIcon.setImageResource(version.getIcon());  
   
   
   
     return convertView;  
   }  



Now after writing getView method our Adapter should look like this.


 package com.technoguff.customadapterexample;  
   
 import android.app.Activity;  
 import android.content.Context;  
 import android.view.LayoutInflater;  
 import android.view.View;  
 import android.view.ViewGroup;  
 import android.widget.ArrayAdapter;  
 import android.widget.ImageView;  
 import android.widget.TextView;  
   
 import java.util.ArrayList;  
 import java.util.List;  
   
 /**  
  * Created by darshanz on 7/13/15.  
  */  
 public class CustomAdapter extends ArrayAdapter<AndroidVersion> {  
   
   
   private ArrayList<AndroidVersion> mVersionList;  
   private LayoutInflater inflater;  
   
   public CustomAdapter(Activity activity, int resource, ArrayList<AndroidVersion> objects) {  
     super(activity, resource, objects);  
   
     mVersionList = objects;  
     inflater = activity.getLayoutInflater();  
   }  
   
   
   @Override  
   public View getView(int position, View convertView, ViewGroup parent) {  
   
     ViewHolder holder;  
   
   
     if(convertView == null){  
       convertView = inflater.inflate(R.layout.layout_item, null);  
       holder = new ViewHolder();  
       holder.tvCodeName = (TextView)convertView.findViewById(R.id.codeName);  
       holder.tvVersion = (TextView)convertView.findViewById(R.id.version);  
       holder.ivIcon = (ImageView)convertView.findViewById(R.id.ivIcon);  
   
       convertView.setTag(holder);  
   
     }else{  
   
       holder = (ViewHolder)convertView.getTag();  
     }  
   
   
     AndroidVersion version = mVersionList.get(position);  
   
     holder.tvCodeName.setText(version.getCodeName());  
     holder.tvVersion.setText(version.getVersion());  
     holder.ivIcon.setImageResource(version.getIcon());  
   
   
   
     return convertView;  
   }  
   
   class ViewHolder{  
     ImageView ivIcon;  
     TextView tvCodeName;  
     TextView tvVersion;  
   }  
   
 }  
   



Finally set this adapter to the listview. In onCreate method of MainActivity, initialize the mListview and set the adapter.

   
     mListView = (ListView)findViewById(R.id.listView);  
     mListView.setAdapter(new CustomAdapter(this, R.layout.layout_item, mVersionList));  
   


Then run the project.





We can see the list items now have images code names and versions.







No comments:

Post a Comment