Wednesday, 22 May 2013

Sectioned List View/ List with Headers in Android

In this post we are going to learn about how to create simple sectioned adapter.

 Additionally we should not do any extra ordinary things. Its an ordinary one with one additional task that's it.

 This sample is not like other sample to set just an simple text view alone. You can use Seperate Header design page for section.

 1. Your Main.xml file



<?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="vertical" >

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

</LinearLayout>

  2. Your Header.xml  // in this file You can design whatever you want.


<TextView 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    android:id="@+id/list_header_title" 
    android:layout_width="fill_parent"  
    android:layout_height="wrap_content" 
    android:paddingTop="2dip" 
    android:paddingBottom="2dip" 
    android:background="#008000"
    android:textColor="@android:color/white"
    android:paddingLeft="5dip" 
    style="?android:attr/listSeparatorTextViewStyle" /> 


3. Your List Childs  // As you peoples know this is also your custom.


<?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:descendantFocusability="blocksDescendants"
    android:orientation="horizontal" >

    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Large Text"
        android:textAppearance="?android:attr/textAppearanceLarge" />
   
    <ImageView
        android:id="@+id/imageView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/ic_launcher" />

   

    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button" />

</LinearLayout>


your MainActivity.java file



package com.example.mysectionadapter;
import java.util.ArrayList;

import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;
import android.widget.Toast;
public class MainActivity extends Activity {       
   
    ListView listView1;
    Context context;
    @Override
    public void onCreate(Bundle icicle) {
        super.onCreate(icicle);
        setContentView(R.layout.homepage);
       
        context=this;
       
        listView1=(ListView)findViewById(R.id.listView1);// list view finding
        // Adding data to array lists
        ArrayList<String> S1 = new ArrayList<String>();
       
        for (int i = 0; i < 10; i++) {
           
            S1.add("S1 item"+i);
        }
       
ArrayList<String> S2 = new ArrayList<String>();
       
        for (int i = 0; i < 10; i++) {
           
            S2.add("S2 item"+i);
        }
       
ArrayList<String> S3 = new ArrayList<String>();
       
        for (int i = 0; i < 10; i++) {
           
            S3.add("S3 item"+i);
        }
       
       
       
       
        // create our list and custom adapter
        SeparatedListAdapter adapter = new SeparatedListAdapter(this);
        adapter.addSection("Header 1 ", new ListAdapter(context,S1));    // this is your first adapter which contains the data related to first header    
        adapter.addSection("Header 2", new ListAdapterTest(context,S2));// this is your second adapter which contains the data related to first header
        adapter.addSection("Header 3 ", new ListAdapter(context,S3));// this is your third adapter which contains the data related to first header        
       
        // the thing is you can set above three adapters as single adapter.. or to differenciate your every single adapter you can use different adapters.
          //if you use different adapters you can use separate design files it will give different look to your ListView.
        // one more thing everything will work under single Scroll.

       
        listView1.setAdapter(adapter);
       
       
        listView1.setOnItemClickListener(new OnItemClickListener() {

            @Override
            public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
                    long arg3) {
                // TODO Auto-generated method stub
                arg2=arg2-1;
               
                Toast.makeText(context, ""+arg2, 1000).show();  
                System.out.println(" TTTTTTTTTTTT " + arg2);
            }
        });

    }

}



SeparatedListAdapter .java  
// this is the master adapter which binds all the adapters as a single adapter with headers.

package com.example.mysectionadapter;

import java.util.LinkedHashMap;
import java.util.Map;
import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Adapter;
import android.widget.ArrayAdapter;
import android.widget.BaseAdapter;

public class SeparatedListAdapter extends BaseAdapter {
   
    public final Map<String,Adapter> sections = new LinkedHashMap<String,Adapter>();
    public final ArrayAdapter<String> headers;
    public final static int TYPE_SECTION_HEADER = 0;
   
    public SeparatedListAdapter(Context context) {

        headers = new ArrayAdapter<String>(context, R.layout.header); // this is the header desing page.

    }
   
    public void addSection(String section, Adapter adapter) {
        this.headers.add(section);
        this.sections.put(section, adapter);
    }
   
    public Object getItem(int position) {
        for(Object section : this.sections.keySet()) {
            Adapter adapter = sections.get(section);
            int size = adapter.getCount() + 1;
           
            // check if position inside this section
            if(position == 0) return section;
            if(position < size) return adapter.getItem(position - 1);

            // otherwise jump into next section
            position -= size;
        }
        return null;
    }

    public int getCount() {
        // total together all sections, plus one for each section header
        int total = 0;
        for(Adapter adapter : this.sections.values())
            total += adapter.getCount() + 1;
        return total;
    }

    public int getViewTypeCount() {
        // assume that headers count as one, then total all sections
        int total = 1;
        for(Adapter adapter : this.sections.values())
            total += adapter.getViewTypeCount();
        return total;
    }
   
    public int getItemViewType(int position) {
        int type = 1;
        for(Object section : this.sections.keySet()) {
            Adapter adapter = sections.get(section);
            int size = adapter.getCount() + 1;
           
            // check if position inside this section
            if(position == 0) return TYPE_SECTION_HEADER; 
            if(position < size) return type + adapter.getItemViewType(position - 1);

            // otherwise jump into next section
            position -= size;
            type += adapter.getViewTypeCount();
        }
        return -1;
    }
   
    public boolean areAllItemsSelectable() {
        return false;
    }

    public boolean isEnabled(int position) {
        return (getItemViewType(position) != TYPE_SECTION_HEADER);
    }
   
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        int sectionnum = 0;
        for(Object section : this.sections.keySet()) {
            Adapter adapter = sections.get(section);
            int size = adapter.getCount() + 1;
           
            // check if position inside this section
            if(position == 0) return headers.getView(sectionnum, convertView, parent); // this is where your header names will get bind. correctly.
            if(position < size) return adapter.getView(position - 1, convertView, parent);

            // otherwise jump into next section
            position -= size;
            sectionnum++;
        }
        return null;
    }

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

}


Adapter files


for sample purpose i have used two adapters. they are as follows.


package com.example.mysectionadapter;
import java.util.ArrayList;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;

public class ListAdapter extends BaseAdapter {
    Context ctx;
    LayoutInflater lInflater;

    ArrayList<String> Datastring=new ArrayList<String>();
   
    public ListAdapter(Context context,ArrayList<String> Items) {
        ctx = context;       
        Datastring.addAll(Items);
        lInflater = (LayoutInflater) ctx
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
       
    }

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

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

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

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
       
        if (convertView == null) {
            convertView = (View) lInflater.inflate(R.layout.list, parent, false);           
        }
        TextView text=(TextView)convertView.findViewById(R.id.textView1);
        text.setText(Datastring.get(position));
       
        return convertView;
    }

   
   

}

Adapter file 2



package com.example.mysectionadapter;
import java.util.ArrayList;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;

public class ListAdapterTest extends BaseAdapter {
    Context ctx;
    LayoutInflater lInflater;

    ArrayList<String> Datastring=new ArrayList<String>();
   
    public ListAdapterTest(Context context,ArrayList<String> Items) {
        ctx = context;       
        Datastring.addAll(Items);
        lInflater = (LayoutInflater) ctx
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
       
    }

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

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

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

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
       
        if (convertView == null) {
            convertView = (View) lInflater.inflate(R.layout.list, parent, false);           
        }
        TextView text=(TextView)convertView.findViewById(R.id.textView1);
        text.setText(Datastring.get(position));
       
        return convertView;
    }

   
   

}

Manifest file . // this is as usual one.



<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.mysectionadapter"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="17" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.example.mysectionadapter.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>


Hope this post will help to some beginners . happy coding.

No comments: