Google+

Friday, March 2, 2012

Custom ListView With Separator and Section in Android



Here we will have a very simple tutorial for Custom ListView in android with Section Header.
We will able to display final view as per below images


 




Steps to Create Custom List View


  1. Open Eclipse to Create New Project.
  2. Create New Project with package name com.sks.demo.custom_list
  3. Add following images in reg->drawable folder



    list_header_bg.9.png
  4. Create a new List Section Header Layout (find the below item_composer_header.xml file)


     <?xml version="1.0" encoding="utf-8"?>  
     <TextView xmlns:android="http://schemas.android.com/apk/res/android"  
       android:id="@+id/list_section_header"  
       android:layout_width="fill_parent"  
       android:layout_height="wrap_content"  
       android:background="@drawable/list_header_bg"  
       android:padding="4dp"  
       android:paddingLeft="10dp"  
       android:shadowColor="#000"  
       android:shadowDx="1"  
       android:shadowDy="1"  
       android:shadowRadius="1"  
       android:text="Header"  
       android:textColor="#FFF"  
       android:textSize="16sp"  
       android:textStyle="bold"  
       android:typeface="serif" />  
    


     
  5. Create a new List Item Custom Layout (find the below item_composer.xml file)
  6.  <?xml version="1.0" encoding="utf-8"?>  
     <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
       android:layout_width="fill_parent"  
       android:layout_height="fill_parent"  
       android:orientation="vertical" >  
       <include  
         android:layout_width="fill_parent"  
         android:layout_height="wrap_content"  
         layout="@layout/item_composer_header" />  
       <LinearLayout  
         android:layout_width="fill_parent"  
         android:layout_height="wrap_content"  
         android:layout_marginLeft="5dp"  
         android:layout_marginRight="5dp"  
         android:background="@drawable/custom_list_item_bg"  
         android:orientation="vertical"  
         android:paddingBottom="3dp"  
         android:paddingLeft="10dp"  
         android:paddingRight="10dp"  
         android:paddingTop="3dp" >  
         <TextView  
           android:id="@+id/list_section_title1"  
           android:layout_width="wrap_content"  
           android:layout_height="wrap_content"  
           android:text="Full Name"  
           android:textColor="@color/white"  
           android:textStyle="bold" />  
         <TextView  
           android:id="@+id/list_section_title2"  
           android:layout_width="wrap_content"  
           android:layout_height="wrap_content"  
           android:text="1500-1600"  
           android:textColor="@color/white" />  
       </LinearLayout>  
     </LinearLayout>  
    


  7.   Now Edit your main.xml to set Custom ListView

     <?xml version="1.0" encoding="utf-8"?>  
     <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
       android:layout_width="fill_parent"  
       android:layout_height="fill_parent"  
       android:background="@drawable/background" >  
       <TextView  
         android:id="@+id/title"  
         android:layout_width="fill_parent"  
         android:layout_height="wrap_content"  
         android:text="State wise Cities in India" />  
       <com.sks.demo.custom_list.list.SKSCustomListView  
         android:id="@+id/list_services"  
         android:layout_width="fill_parent"  
         android:layout_height="fill_parent"  
         android:layout_below="@+id/title"  
         android:background="#00ffffff"  
         android:cacheColorHint="#00000000"  
         android:divider="@drawable/img_list_seperator"  
         android:dividerHeight="1dip"  
         android:drawingCacheQuality="high"  
         android:keepScreenOn="false" >  
       </com.sks.demo.custom_list.list.SKSCustomListView>  
     </RelativeLayout>  
    




    The Above code will be look like below image. You can set any background.



  8. Here we are going to create our custom list view Widget. 
    • We need to set Some Data & Composer classes for list view item
    • Following is the Data & Composer Class in Default Package

      Code : Data.java
       package com.sks.demo.custom_list;  
       import java.util.ArrayList;  
       import java.util.Arrays;  
       import java.util.List;  
       import android.os.SystemClock;  
       import android.util.Pair;  
       public class Data {  
           public static List<Pair<String, List<Composer>>> getAllData() {  
               List<Pair<String, List<Composer>>> res = new ArrayList<Pair<String, List<Composer>>>();  
               for (int i = 0; i < 4; i++) {  
                   res.add(getOneSection(i));  
               }  
               return res;  
           }  
           public static List<Composer> getFlattenedData() {  
               List<Composer> res = new ArrayList<Composer>();  
               for (int i = 0; i < 4; i++) {  
                   res.addAll(getOneSection(i).second);  
               }  
               return res;  
           }  
           public static Pair<Boolean, List<Composer>> getRows(int page) {  
               List<Composer> flattenedData = getFlattenedData();  
               if (page == 1) {  
                   return new Pair<Boolean, List<Composer>>(true, flattenedData.subList(0, 5));  
               } else {  
                   SystemClock.sleep(2000); // simulate loading  
                   return new Pair<Boolean, List<Composer>>(page * 5 < flattenedData.size(), flattenedData.subList((page) * 5,  
                           Math.min(page * 5, flattenedData.size())));  
               }  
           }  
           public static Pair<String, List<Composer>> getOneSection(int index) {  
               String[] titles =  
               {  
                       "Maharashtra",  
                       "Gujarat",  
                       "Jammu",  
                       "Punjab"  
               };  
               Composer[][] composerss =  
               {  
                       {  
                               new Composer("Amravati", "2,607,160"),  
                               new Composer("Aurangabad", "2,897,103"),  
                               new Composer("Khandala", "21,043"),  
                               new Composer("Mumbai", "11,914,398"),  
                               new Composer("Nagpur", "2,420,000"),  
                               new Composer("Pune", "4,485,000"),  
                       },  
                       {  
                               new Composer("Ahmedabad", "3,913,793"),  
                               new Composer("Surat", "3,344,135"),  
                               new Composer("Vadodara", "1,513,758"),  
                               new Composer("Rajkot", "1,395,026"),  
                               new Composer("Gandhinagar", "271,331"),  
                               new Composer("Bhavnagar", "600,594"),  
                       },  
                       {  
                               new Composer("Kathua", "550,084"),  
                               new Composer("Jammu", "1,343,756"),  
                               new Composer("Samba", "245,016"),  
                               new Composer("Udhampur", "475,068"),  
                               new Composer("Reasi", "268,441"),  
                               new Composer("Rajouri", "483,284"),  
                       },  
                       {  
                               new Composer("Amritsar", "1,183,705"),  
                               new Composer("Firozpur", "110,091"),  
                               new Composer("Ludhiana", "1,613,878"),  
                               new Composer("Chandigarh", "27,704,236"),  
                               new Composer("Jalandhar ", "873,725"),  
                               new Composer("Patiala", "445,196"),  
                       },  
               };  
               return new Pair<String, List<Composer>>(titles[index], Arrays.asList(composerss[index]));  
           }  
       }  
      

      Code : Composer.java
       package com.sks.demo.custom_list;  
       public class Composer {  
           public static final String TAG = Composer.class.getSimpleName();  
           public String name;  
           public String year;  
           public Composer(String name, String year) {  
               this.name = name;  
               this.year = year;  
           }  
       }  
      


  9. Now Create Custom List & Adapter
    • Create New Package com.sks.demo.custom_list.list
    • Create new class SKSCustomListAdapter.java
    • Write code for SKSCustomListAdapter.java

       package com.sks.demo.custom_list.list;  
       import android.view.View;  
       import android.view.ViewGroup;  
       import android.widget.AbsListView;  
       import android.widget.AbsListView.OnScrollListener;  
       import android.widget.BaseAdapter;  
       import android.widget.SectionIndexer;  
       public abstract class SKSCustomListAdapter extends BaseAdapter implements SectionIndexer, OnScrollListener {  
           public static final String TAG = SKSCustomListAdapter.class.getSimpleName();  
           public interface HasMorePagesListener {  
               void noMorePages();  
               void mayHaveMorePages();  
           }  
           /**  
            * The <em>current</em> page, not the page that is going to be loaded.  
            */  
           int page = 1;  
           int initialPage = 1;  
           boolean automaticNextPageLoading = false;  
           HasMorePagesListener hasMorePagesListener;  
           void setHasMorePagesListener(HasMorePagesListener hasMorePagesListener) {  
               this.hasMorePagesListener = hasMorePagesListener;  
           }  
         /**  
          * Pinned header state: don't show the header.  
          */  
         public static final int PINNED_HEADER_GONE = 0;  
         /**  
          * Pinned header state: show the header at the top of the list.  
          */  
         public static final int PINNED_HEADER_VISIBLE = 1;  
         /**  
          * Pinned header state: show the header. If the header extends beyond  
          * the bottom of the first shown element, push it up and clip.  
          */  
         public static final int PINNED_HEADER_PUSHED_UP = 2;  
         /**  
          * Computes the desired state of the pinned header for the given  
          * position of the first visible list item. Allowed return values are  
          * {@link #PINNED_HEADER_GONE}, {@link #PINNED_HEADER_VISIBLE} or  
          * {@link #PINNED_HEADER_PUSHED_UP}.  
          */  
         public int getPinnedHeaderState(int position) {  
             if (position < 0 || getCount() == 0) {  
                 return PINNED_HEADER_GONE;  
             }  
             // The header should get pushed up if the top item shown  
             // is the last item in a section for a particular letter.  
             int section = getSectionForPosition(position);  
             int nextSectionPosition = getPositionForSection(section + 1);  
             if (nextSectionPosition != -1 && position == nextSectionPosition - 1) {  
                 return PINNED_HEADER_PUSHED_UP;  
             }  
             return PINNED_HEADER_VISIBLE;  
         }  
         /**  
          * Sets the initial page when {@link #resetPage()} is called.  
          * Default is 1 (for APIs with 1-based page number).  
          */  
         public void setInitialPage(int initialPage) {  
               this.initialPage = initialPage;  
           }  
         /**  
          * Resets the current page to the page specified in {@link #setInitialPage(int)}.  
          */  
         public void resetPage() {  
             this.page = this.initialPage;  
         }  
         /**  
          * Increases the current page number.  
          */  
         public void nextPage() {  
             this.page++;  
         }  
           @Override  
           public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {  
               if (view instanceof SKSCustomListView) {  
                   ((SKSCustomListView) view).configureHeaderView(firstVisibleItem);  
               }  
           }  
           @Override  
           public void onScrollStateChanged(AbsListView view, int scrollState) {  
               // nop  
           }  
           @Override  
           public final View getView(int position, View convertView, ViewGroup parent) {  
               View res = getAmazingView(position, convertView, parent);  
               if (position == getCount() - 1 && automaticNextPageLoading) {  
                   onNextPageRequested(page + 1);  
               }  
               final int section = getSectionForPosition(position);  
               boolean displaySectionHeaders = (getPositionForSection(section) == position);  
               bindSectionHeader(res, position, displaySectionHeaders);  
               return res;  
           }  
           public void notifyNoMorePages() {  
               automaticNextPageLoading = false;  
               if (hasMorePagesListener != null) hasMorePagesListener.noMorePages();  
           }  
           public void notifyMayHaveMorePages() {  
               automaticNextPageLoading = true;  
               if (hasMorePagesListener != null) hasMorePagesListener.mayHaveMorePages();  
           }  
           /**  
            * The last item on the list is requested to be seen, so do the request   
            * and call {@link SKSCustomListView#tellNoMoreData()} if there is no more pages.  
            *   
            * @param page the page number to load.  
            */  
           protected abstract void onNextPageRequested(int page);  
           /**  
            * Configure the view (a listview item) to display headers or not based on displaySectionHeader   
            * (e.g. if displaySectionHeader header.setVisibility(VISIBLE) else header.setVisibility(GONE)).  
            */  
           protected abstract void bindSectionHeader(View view, int position, boolean displaySectionHeader);  
           /**  
            * read: get view too  
            */  
           public abstract View getAmazingView(int position, View convertView, ViewGroup parent);  
         /**  
          * Configures the pinned header view to match the first visible list item.  
          *  
          * @param header pinned header view.  
          * @param position position of the first visible list item.  
          * @param alpha fading of the header view, between 0 and 255.  
          */  
         public abstract void configurePinnedHeader(View header, int position, int alpha);  
           @Override  
           public abstract int getPositionForSection(int section);  
           @Override  
           public abstract int getSectionForPosition(int position);  
           @Override  
           public abstract Object[] getSections();  
       }  
      
    • Create new Class SKSCustomListView.java
    • Write code for SKSCustomListView.java
       package com.sks.demo.custom_list.list;  
       import android.content.Context;  
       import android.graphics.Canvas;  
       import android.util.AttributeSet;  
       import android.view.View;  
       import android.widget.ListAdapter;  
       import android.widget.ListView;  
       import com.sks.demo.custom_list.list.SKSCustomListAdapter.HasMorePagesListener;  
       /**  
        * A ListView that maintains a header pinned at the top of the list. The pinned  
        * header can be pushed up and dissolved as needed.  
        *   
        * It also supports pagination by setting a custom view as the loading  
        * indicator.  
        */  
       public class SKSCustomListView extends ListView implements HasMorePagesListener {  
           View listFooter;  
           boolean footerViewAttached = false;  
           private View mHeaderView;  
           private boolean mHeaderViewVisible;  
           private int mHeaderViewWidth;  
           private int mHeaderViewHeight;  
           private SKSCustomListAdapter adapter;  
           public void setPinnedHeaderView(View view) {  
               mHeaderView = view;  
               // Disable vertical fading when the pinned header is present  
               // TODO change ListView to allow separate measures for top and bottom  
               // fading edge;  
               // in this particular case we would like to disable the top, but not the  
               // bottom edge.  
               if (mHeaderView != null) {  
                   setFadingEdgeLength(0);  
               }  
               requestLayout();  
           }  
           @Override  
           protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {  
               super.onMeasure(widthMeasureSpec, heightMeasureSpec);  
               if (mHeaderView != null) {  
                   measureChild(mHeaderView, widthMeasureSpec, heightMeasureSpec);  
                   mHeaderViewWidth = mHeaderView.getMeasuredWidth();  
                   mHeaderViewHeight = mHeaderView.getMeasuredHeight();  
               }  
           }  
           @Override  
           protected void onLayout(boolean changed, int left, int top, int right, int bottom) {  
               super.onLayout(changed, left, top, right, bottom);  
               if (mHeaderView != null) {  
                   mHeaderView.layout(0, 0, mHeaderViewWidth, mHeaderViewHeight);  
                   configureHeaderView(getFirstVisiblePosition());  
               }  
           }  
           public void configureHeaderView(int position) {  
               if (mHeaderView == null) {  
                   return;  
               }  
               int state = adapter.getPinnedHeaderState(position);  
               switch (state) {  
               case SKSCustomListAdapter.PINNED_HEADER_GONE: {  
                   mHeaderViewVisible = false;  
                   break;  
               }  
               case SKSCustomListAdapter.PINNED_HEADER_VISIBLE: {  
                   adapter.configurePinnedHeader(mHeaderView, position, 255);  
                   if (mHeaderView.getTop() != 0) {  
                       mHeaderView.layout(0, 0, mHeaderViewWidth, mHeaderViewHeight);  
                   }  
                   mHeaderViewVisible = true;  
                   break;  
               }  
               case SKSCustomListAdapter.PINNED_HEADER_PUSHED_UP: {  
                   View firstView = getChildAt(0);  
                   if (firstView != null) {  
                       int bottom = firstView.getBottom();  
                       int headerHeight = mHeaderView.getHeight();  
                       int y;  
                       int alpha;  
                       if (bottom < headerHeight) {  
                           y = (bottom - headerHeight);  
                           alpha = 255 * (headerHeight + y) / headerHeight;  
                       } else {  
                           y = 0;  
                           alpha = 255;  
                       }  
                       adapter.configurePinnedHeader(mHeaderView, position, alpha);  
                       if (mHeaderView.getTop() != y) {  
                           mHeaderView.layout(0, y, mHeaderViewWidth, mHeaderViewHeight + y);  
                       }  
                       mHeaderViewVisible = true;  
                   }  
                   break;  
               }  
               }  
           }  
           @Override  
           protected void dispatchDraw(Canvas canvas) {  
               super.dispatchDraw(canvas);  
               if (mHeaderViewVisible) {  
                   drawChild(canvas, mHeaderView, getDrawingTime());  
               }  
           }  
           public SKSCustomListView(Context context) {  
               super(context);  
           }  
           public SKSCustomListView(Context context, AttributeSet attrs) {  
               super(context, attrs);  
           }  
           public SKSCustomListView(Context context, AttributeSet attrs, int defStyle) {  
               super(context, attrs, defStyle);  
           }  
           public void setLoadingView(View listFooter) {  
               this.listFooter = listFooter;  
           }  
           public View getLoadingView() {  
               return listFooter;  
           }  
           @Override  
           public void setAdapter(ListAdapter adapter) {  
               if (!(adapter instanceof SKSCustomListAdapter)) {  
                   throw new IllegalArgumentException(SKSCustomListView.class.getSimpleName() + " must use adapter of type "  
                           + SKSCustomListAdapter.class.getSimpleName());  
               }  
               // previous adapter  
               if (this.adapter != null) {  
                   this.adapter.setHasMorePagesListener(null);  
                   this.setOnScrollListener(null);  
               }  
               this.adapter = (SKSCustomListAdapter) adapter;  
               ((SKSCustomListAdapter) adapter).setHasMorePagesListener(this);  
               this.setOnScrollListener((SKSCustomListAdapter) adapter);  
               View dummy = new View(getContext());  
               super.addFooterView(dummy);  
               super.setAdapter(adapter);  
               super.removeFooterView(dummy);  
           }  
           @Override  
           public SKSCustomListAdapter getAdapter() {  
               return adapter;  
           }  
           @Override  
           public void noMorePages() {  
               if (listFooter != null) {  
                   this.removeFooterView(listFooter);  
               }  
               footerViewAttached = false;  
           }  
           @Override  
           public void mayHaveMorePages() {  
               if (!footerViewAttached && listFooter != null) {  
                   this.addFooterView(listFooter);  
                   footerViewAttached = true;  
               }  
           }  
           public boolean isLoadingViewVisible() {  
               return footerViewAttached;  
           }  
       }  
      
  10. Finally We reach to create our Start-up Activity named as CustomListDemoActivity.java  
    • In main package i.e. com.sks.demo.custom_list Create new Activity  CustomListDemoActivity.java
    • Write code for CustomListDemoActivity.java
      Code :  CustomListDemoActivity.java 
       package com.sks.demo.custom_list;  
       import java.util.List;  
       import android.app.Activity;  
       import android.content.Context;  
       import android.os.Bundle;  
       import android.util.Log;  
       import android.util.Pair;  
       import android.view.LayoutInflater;  
       import android.view.View;  
       import android.view.ViewGroup;  
       import android.widget.AdapterView;  
       import android.widget.AdapterView.OnItemClickListener;  
       import android.widget.TextView;  
       import com.sks.demo.custom_list.list.SKSCustomListAdapter;  
       import com.sks.demo.custom_list.list.SKSCustomListView;  
       public class CustomListDemoActivity extends Activity {  
           SKSCustomListView lsComposer;  
           SectionComposerAdapter adapter;  
           Context context;  
           /** Called when the activity is first created. */  
           @Override  
           public void onCreate(Bundle savedInstanceState) {  
               super.onCreate(savedInstanceState);  
               setContentView(R.layout.main);  
               context = getParent();  
           }  
           @Override  
           protected void onStart() {  
               super.onStart();  
               initializedView();  
               setupFunctionality();  
               setupListeners();  
           }  
           private void initializedView() {  
               lsComposer = (SKSCustomListView) findViewById(R.id.list_services);  
           }  
           private void setupFunctionality() {  
               lsComposer.setPinnedHeaderView(LayoutInflater.from(this).inflate(R.layout.item_composer_header, lsComposer, false));  
               lsComposer.setAdapter(adapter = new SectionComposerAdapter());  
               lsComposer.setOnItemClickListener(new OnItemClickListener() {  
                   @Override  
                   public void onItemClick(AdapterView<?> parent, View view, int position, long id) {  
                       // Intent intent = new Intent(CustomListDemoActivity.this,  
                       // ServiceDestailsScreen.class);  
                       String name, address, title;  
                       title = ((TextView) view.findViewById(R.id.list_section_header)).getText().toString();  
                       name = ((TextView) view.findViewById(R.id.list_section_title1)).getText().toString();  
                       address = ((TextView) view.findViewById(R.id.list_section_title2)).getText().toString();  
                       // intent.putExtra("serviceName", title);  
                       // intent.putExtra("name", name);  
                       // intent.putExtra("address", address);  
                       Log.v(Util.TAG, "Name : " + name);  
                       Log.v(Util.TAG, "Address : " + address);  
                       Log.v(Util.TAG, "Title: " + title);  
                       // getParent().startActivity(intent);  
                   }  
               });  
           }  
           private void setupListeners() {  
               // titleBack.setOnClickListener(this);  
           }  
           class SectionComposerAdapter extends SKSCustomListAdapter {  
               List<Pair<String, List<Composer>>> all = Data.getAllData();  
               @Override  
               public int getCount() {  
                   int res = 0;  
                   for (int i = 0; i < all.size(); i++) {  
                       res += all.get(i).second.size();  
                   }  
                   return res;  
               }  
               @Override  
               public Composer getItem(int position) {  
                   int c = 0;  
                   for (int i = 0; i < all.size(); i++) {  
                       if (position >= c && position < c + all.get(i).second.size()) {  
                           return all.get(i).second.get(position - c);  
                       }  
                       c += all.get(i).second.size();  
                   }  
                   return null;  
               }  
               @Override  
               public long getItemId(int position) {  
                   return position;  
               }  
               @Override  
               protected void onNextPageRequested(int page) {  
               }  
               @Override  
               protected void bindSectionHeader(View view, int position, boolean displaySectionHeader) {  
                   if (displaySectionHeader) {  
                       view.findViewById(R.id.list_section_header).setVisibility(View.VISIBLE);  
                       TextView lSectionTitle = (TextView) view.findViewById(R.id.list_section_header);  
                       lSectionTitle.setText(getSections()[getSectionForPosition(position)]);  
                   } else {  
                       TextView lSectionTitle = (TextView) view.findViewById(R.id.list_section_header);  
                       lSectionTitle.setText(getSections()[getSectionForPosition(position)]);  
                       view.findViewById(R.id.list_section_header).setVisibility(View.GONE);  
                   }  
               }  
               @Override  
               public View getAmazingView(int position, View convertView, ViewGroup parent) {  
                   View res = convertView;  
                   if (res == null)  
                       res = getLayoutInflater().inflate(R.layout.item_composer, null);  
                   TextView lName = (TextView) res.findViewById(R.id.list_section_title1);  
                   TextView lYear = (TextView) res.findViewById(R.id.list_section_title2);  
                   Composer composer = getItem(position);  
                   lName.setText(composer.name);  
                   lYear.setText("Population : " + composer.year);  
                   return res;  
               }  
               @Override  
               public void configurePinnedHeader(View header, int position, int alpha) {  
                   TextView lSectionHeader = (TextView) header;  
                   lSectionHeader.setText(getSections()[getSectionForPosition(position)]);  
                   // lSectionHeader.setBackgroundColor(alpha << 24 | (0xbbffbb));  
                   // lSectionHeader.setTextColor(alpha << 24 | (0x000000));  
               }  
               @Override  
               public int getPositionForSection(int section) {  
                   if (section < 0)  
                       section = 0;  
                   if (section >= all.size())  
                       section = all.size() - 1;  
                   int c = 0;  
                   for (int i = 0; i < all.size(); i++) {  
                       if (section == i) {  
                           return c;  
                       }  
                       c += all.get(i).second.size();  
                   }  
                   return 0;  
               }  
               @Override  
               public int getSectionForPosition(int position) {  
                   int c = 0;  
                   for (int i = 0; i < all.size(); i++) {  
                       if (position >= c && position < c + all.get(i).second.size()) {  
                           return i;  
                       }  
                       c += all.get(i).second.size();  
                   }  
                   return -1;  
               }  
               @Override  
               public String[] getSections() {  
                   String[] res = new String[all.size()];  
                   for (int i = 0; i < all.size(); i++) {  
                       res[i] = all.get(i).first;  
                   }  
                   return res;  
               }  
           }  
       }  
      
    • Make sure the changes in AndroidMenifest.xml

      Code : AndroidMenifest.xml
       <?xml version="1.0" encoding="utf-8"?>  
       <manifest xmlns:android="http://schemas.android.com/apk/res/android"  
         package="com.sks.demo.custom_list"  
         android:versionCode="1"  
         android:versionName="1.0" >  
         <uses-sdk android:minSdkVersion="8" />  
         <application  
           android:icon="@drawable/ic_launcher"  
           android:label="@string/app_name" >  
           <activity  
             android:name=".CustomListDemoActivity"  
             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>  
      
  11. Finally Code writing work has been complete. Start compiling Android project.
  12. Run the project.
  13. Result will be like below
  
Download Source Code and  Installer Apk

SVN Repository


Enjoy the Code and do not forget to leave comments.

15 comments:

Anonymous said...

The SVN Link is down :(

Sachin Shelke said...

Hi,
Its Working Now... Please Check ... :)

Anonymous said...

hi in this pinned listview when we scroll down to bottom of the listview both the section are visible how to remove that one

Sachin Shelke said...

hello,
basically the purpose of this ListView is as given in screenshot.

have a look of iPhone contact list, if you scroll up or down it will show you section header of hidden item also.

if you need to use non pinned header then refer below link
http://developer.android.com/reference/android/widget/SectionIndexer.html

Anonymous said...

hi thanks for the replay in your data.class you have defined titles and composerss with fixed sizes how can i define dynamic those two things. i have used arraylist in place of array but it is not generating the list view. so how those two should be initialized dynamically?

Sachin Shelke said...

This is a nice question...
Well if we talk about Composer.java
It is for Holding data at run-time like customization.

now if we talk about Data.java, here is the main challenge.

till now there is no constructor for Data.java
so you can create the constructor with argument List<Pair<String, List<Composer>>>
For Ex.


public Data(List<Pair<String, List<Composer>>> myListContaint)
{
......
}

now change the static value of for loop to dynamic by getting myListContaint size or count;

if possible remove the static keyword of every method from Data.java and make changes in code accordingly.

It should work.

Let me know if you face any difficulties.

manjul said...

Hi... am getting an error in CustomListActivity.java in main package at (Log.v(util.TAG, + "Name : =" + name) and
(Log.v(util.TAG, + "Title: =" + title) and
(Log.v(util.TAG, + "Address: =" + address)....

I'm getting an error as
"util cannot be resolved to a variable".. please help me.

Sachin Shelke said...

Hi,
just replace util.TAG by any string object. for Ex. "CustomList"

it should work. or checkout project from SVN repository

Surya Kumar said...

Thanks . Code really helped me

Jitendra Kumar said...
This comment has been removed by the author.
Jitendra Kumar said...

i want to use this custom list with database can u plz help me where i should change in which file. i have dummy data set with me.thnx

Sachin Shelke said...

Hi Jitendra Kumar,
Just check comment on below link, you will get help
http://smartphonebysachin.blogspot.in/2012/03/custom-listview-with-separator-and.html?showComment=1335949651533#c5341016054674069826

Mehul Joisar said...

Hi,thanks for such a nice piece of code.
I have a confusion over here.
I have total 3 Array of String to display its content in "list_section_header","list_section_title1","list_section_title2".

Can you please guide me to modify the code ?
I would be really grateful if you can guide me towards my target.
:-)

robhic montecinos said...

Hi Sachin, you very good example, excuse my English, but I need your help, at the end of each section, I need to add an item "More data" (footer), in order to show more results, as could do that. I would greatly appreciate you can help.
Regards, Roberto

devika said...

Hello Can you Please tell me how do i add 2 arraylist into this. I need 2 arraylist in my example here you have one list and String, how do i add another list or arraylist insted of String??? Please Help!!!!
Thank you

Google+