Tuesday 22 January 2013

How Adapters works in Android

Adapters
       An Adapter object acts as a bridge between a View and the underlying data for that view. The Adapter provides access to the data items. The Adapter is also responsible for making a View for each item in the data set.The adapter also defines how each row is theListView is displayed. 

Adapter implementations
       An adapter extend the BaseAdapter class. Android  provides some standard adapters; the most important are Array Adapter , Cursor Adapter , Simple CursorAdapter.
Array Adapter
It is an adapter of information for lists. It uses an array of objects. Array Adapter you use it in two ways:
>> ArrayAdapter TextView with array. (ArrayAdapter(Context context, int textViewResourceId, T[] objects).
>> ArrayAdapter TextView with list. (ArrayAdapter(Context context, int textViewResourceId, List<T> objects).
Cursor Adapter
      Basically Cursor is an interface. Cursor provides random read-write access to the result . Adapter that exposes data from a Cursor to a ListView widget.
Simple Cursor Adapter
   Basically Simple Cursor Adapter used to map columns from a cursor to TextViews or ImageViews defined in an XML file. You can specify which columns you want, which views you want to display the columns, and the XML file that defines the appearance of these views. The General format of this adapter is: SimpleCursorAdapter (Context context, int layout, Cursor c, String[] from, int[] to) . 







Monday 7 January 2013

ListView Items with Custom Adapter in Android


Android ListView Items with Custom Adapter


In this tutorial, it will help you to know about Custom Adapter and ListView.
Create a new Android project in Eclipse with MainActivity as your default Activity and main.xml as your default layout file. Declare a ListView control in your main.xml layout file as shown in the following code.
Main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="#FFFFFF">
   
     <ListView
        android:id="@+id/listView1"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" />
    
</LinearLayout>

The above code is using simple LinearLayout with vertical orientation, and a ListView is declared to cover the entire width and height of the parent container using the fill_parent as the value of both android:layout_heightand android:layout:width properties. ListView also has a unique id listView1 that will be used in the MainActivity to reference the ListView control. 
To create the custom header for the ListView, create a new xml layout file main_header.xml in the layout folder of your project and declare a TextView control in it with the properties shown in the following code. This will create a blue header with the white color text showing Contacts.


Main_header.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
       
     <TextView android:id="@+id/txtHeader"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:gravity="center_vertical"
        android:textStyle="bold"
        android:textSize="22dp"
        android:textColor="#FFFFFF"
        android:padding="10dp"
        android:text="Contacts"
        android:background="#336699" />

</LinearLayout>


To create a custom ListView row, create another xml layout file listview_item_row.xml in the project layout directory. Android will render this file content in every ListView item and you are free to declare any control you want in it. For this tutorial I am using an ImageView for an icon and a TextView for displaying items titles. Following is the code for listview_item.xml file.


Listview_item.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <ImageView
        android:id="@+id/imageView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:src="@drawable/email_icon" />

    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBottom="@+id/imageView1"
        android:layout_marginLeft="22dp"
        android:layout_toRightOf="@+id/imageView1"
        android:text="Medium Text"
        android:textAppearance="?android:attr/textAppearanceMedium" />

</RelativeLayout>


Next create a new Java class in your project and named it Contacts.java. This class will be used to create a custom ArrayAdapter and to bind the objects with the ListView later in this tutorial. Following is the code of Contacts.java class. It has two simple properties icon and title and a typical class constructor to initialize the properties. 
public class Contacts
{
      public int icon;
      public String title;
     
      public Contacts() {
            super();
            // TODO Auto-generated constructor stub
      }
     
        public Contacts(int icon, String title) {
              super();
              this.icon = icon;
              this.title = title;
          }
}

Notice that the above listview_item.xml file has two views, which are correspondent to the properties of the Contacts class. The values of the Weather class properties will be displayed on those views and to connect these two pieces together you need to create a custom ArrayAdapter that will inherit the Android ArrayAdapter class and will override the getView method. Add a new java class in your project with the name  ContactsAdapter and implement the code as shown below:

public class ContactsAdapter extends ArrayAdapter<Contacts>
{
            Context context;
          int layoutResourceId;   
          Weather data[] = null;
          public ContactsAdapter(Context context, int layoutResourceId, Contacts[] data)
          {
            super(context, layoutResourceId, data);
            this.layoutResourceId = layoutResourceId;
              this.context = context;
              this.data = data;
          }
         
          @Override
          public View getView(int position, View convertView, ViewGroup parent) {
          // TODO Auto-generated method stub
           
            View row = convertView;
            ContactsHolder holder = null;
            if(row == null)
            {
                  LayoutInflater inflater = ((Activity)context).getLayoutInflater();
                  row = inflater.inflate(layoutResourceId, parent, false);
                 
                  holder = new ContactsHolder();
                  holder.imgIcon = (ImageView)row.findViewById(R.id.imageView1);
                   holder.txtTitle = (TextView)row.findViewById(R.id.textView1);
                  
                   row.setTag(holder);
            }
            else
              {
                  holder = (ContactsHolder)row.getTag();
              }
             
              Contacts con = data[position];
              holder.txtTitle.setText(con.title);
              holder.imgIcon.setImageResource(con.icon);
             
              return row;
          }
         
         
          static class ContactsHolder
          {
              ImageView imgIcon;
              TextView txtTitle;
          }
         
         
         
}

In the above code, the first important thing is the constructor of the class that takes three parameters. The first parameter is the Context and we can pass the reference of the activity in which we will use ContactsAdapterclass. The second parameter is the resource id of the layout file we want to use for displaying each ListView item. We will pass the resource id of our layout file listview_item.xml for this parameter. The third parameter is an array of Contacts class objects that will be used by the Adapter to display data. 

Next the parent class getView method is overridden. This method will be called for every item in the ListView to create views with their properties set as we want. The getView method is also using a temporary holder class declared inside the ContactsAdapter class. This class will be used to cache the ImageView and TextView so they can be reused for every row in the ListView and this will provide us a great performance improvement as we are recycling the same two views with different properties and we don’t need to find ImageView and TextView for every ListView item. The above code is also using the Android built in Layout Inflator to inflate (parse) the xml layout file. 

The final piece of code is our application MainActivity in which we will be using all the above objects we declared. Following is the code of the Home.java file.
public class Home extends Activity {
     
      private ListView lv;
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
       
       
        Contacts data[] = new Contacts[]
                                     {
                                new Contacts(R.drawable.email_icon,"Tara"),
                                new Contacts(R.drawable.email_icon,"Neo")
                                     };
       
        ContactsAdapter adapter = new ContactsAdapter(this, R.layout.listview_item, data);
       
        lv = (ListView)findViewById(R.id.listView1);
       
        View header = (View)getLayoutInflater().inflate(R.layout.main_headernull);
        lv.addHeaderView(header);
       
        lv.setAdapter(adapter);
       
    }
}

Now You run this program & see Output: