[Tut]Using AlphabetIndexer for fastscrolling ListView

Tutorials with advanced 'difficulty' and more Lines of Code.

[Tut]Using AlphabetIndexer for fastscrolling ListView

Postby qlimax » Wed Jan 13, 2010 8:38 pm

Hi everybody,

someone asked me how to use the AlphabetIndexer class, provided by the android framework, to build a fastscroll listview which uses A-Z indexing

the last tutorial I wrote, http://www.anddev.org/tutalphabetic_fas ... 10123.html,
describes how to build an AZ indexed listview using your own arraylist of objects.

This tutorial explain how build an indexed listview using an ordered cursor,
yes, because the context in witch you can use the AlphabetIndexer class, is when you have an ordered cursor as a source data for the listview.

But let's speak the code !

Syntax: [ Download ] [ Hide ]
Using xml Syntax Highlighting
  1. <?xml version="1.0" encoding="utf-8"?>
  2.  
  3. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  4.  
  5.    android:orientation="vertical"
  6.  
  7.    android:layout_width="fill_parent"
  8.  
  9.    android:layout_height="fill_parent"
  10.  
  11.    >
  12.  
  13.  
  14.  
  15. <ListView
  16.  
  17. android:id="@+id/myListView"
  18.  
  19. android:layout_width="wrap_content"
  20.  
  21. android:layout_height="wrap_content">
  22.  
  23. </ListView>
  24.  
  25.  
  26.  
  27. </LinearLayout>
Parsed in 0.002 seconds, using GeSHi 1.0.8.4



the purpose of the class below, is to populate a db from which the Cursor will be extracted
In most cases you can omit that class, because you already have your ordered cursor...
Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1. package ch.egsolutions.alpha;
  2.  
  3.  
  4.  
  5. import java.util.Random;
  6.  
  7.  
  8.  
  9. import android.content.ContentValues;
  10.  
  11. import android.content.Context;
  12.  
  13. import android.database.Cursor;
  14.  
  15. import android.database.sqlite.SQLiteDatabase;
  16.  
  17. import android.database.sqlite.SQLiteOpenHelper;
  18.  
  19. import android.util.Log;
  20.  
  21.  
  22.  
  23.  
  24.  
  25. public class DbUtil  {
  26.  
  27.  
  28.  
  29.        
  30.  
  31.  
  32.  
  33.         static final String KEY_ID="_id";
  34.  
  35.         static final String KEY_NAME="name";
  36.  
  37.  
  38.  
  39.        
  40.  
  41.     private static final String DB_NAME="tutorial";
  42.  
  43.         private static final String TABLE_NAME="names";
  44.  
  45.         private static final int DATABASE_VERSION = 1;
  46.  
  47.  
  48.  
  49.         private static final String DATABASE_CREATE =
  50.  
  51.                 "create table "+TABLE_NAME+" ("+KEY_ID+" integer primary key autoincrement, "
  52.  
  53.                 + KEY_NAME+" varchar not null);";
  54.  
  55.  
  56.  
  57.         private Context context;
  58.  
  59.         private DatabaseHelper dbHelper;
  60.  
  61.         private SQLiteDatabase db;
  62.  
  63.        
  64.  
  65.        
  66.  
  67.         public DbUtil(Context context){
  68.  
  69.                 this.context=context;
  70.  
  71.                 this.dbHelper=new DatabaseHelper(this.context);
  72.  
  73.         }
  74.  
  75.        
  76.  
  77.         private static class DatabaseHelper extends SQLiteOpenHelper
  78.  
  79.     {
  80.  
  81.         DatabaseHelper(Context context)
  82.  
  83.         {
  84.  
  85.             super(context, DB_NAME, null, DATABASE_VERSION);
  86.  
  87.         }
  88.  
  89.  
  90.  
  91.         @Override
  92.  
  93.         public void onCreate(SQLiteDatabase db)
  94.  
  95.         {
  96.  
  97.             db.execSQL(DATABASE_CREATE);
  98.  
  99.         }
  100.  
  101.  
  102.  
  103.         @Override
  104.  
  105.         public void onUpgrade(SQLiteDatabase db, int oldVersion,
  106.  
  107.                               int newVersion)
  108.  
  109.         {
  110.  
  111.             Log.v("DBUTIL", "Upgrading database from version " + oldVersion
  112.  
  113.                   + " to "
  114.  
  115.                   + newVersion + ", which will destroy all old data");
  116.  
  117.             db.execSQL("DROP TABLE IF EXISTS "+TABLE_NAME);
  118.  
  119.             onCreate(db);
  120.  
  121.         }
  122.  
  123.     }    
  124.  
  125.  
  126.  
  127.         public void open(){
  128.  
  129.                 db=dbHelper.getWritableDatabase();
  130.  
  131.         }
  132.  
  133.         public void close(){
  134.  
  135.                 dbHelper.close();
  136.  
  137.         }
  138.  
  139.        
  140.  
  141.        
  142.  
  143.        
  144.  
  145.         public void insertRandomNames(){
  146.  
  147.                 db.execSQL("DELETE FROM "+TABLE_NAME);
  148.  
  149.                 String s = "QWERTZUIOPASDFGHJKLYXCVBNM";
  150.  
  151.                 Random r = new Random();
  152.  
  153.                
  154.  
  155.                 ContentValues values=new ContentValues() ;
  156.  
  157.                 for(int i=0;i<200;i++){
  158.  
  159.                         values.clear();
  160.  
  161.                 values.put(KEY_NAME, s.substring(r.nextInt(s.length())));
  162.  
  163.                 db.insert(TABLE_NAME, null, values);
  164.  
  165.                 }
  166.  
  167.         }
  168.  
  169.        
  170.  
  171.         public Cursor fetchAllData(){
  172.  
  173.                 return db.rawQuery("SELECT * FROM "+TABLE_NAME+" ORDER BY "+KEY_NAME+" ASC", null);            
  174.  
  175.         }
  176.  
  177.        
  178.  
  179. }
  180.  
  181.  
Parsed in 0.040 seconds, using GeSHi 1.0.8.4




Now: Activity + MyCursorAdapter
(comments in the code)

Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1. package ch.egsolutions.alpha;
  2.  
  3. import android.app.Activity;
  4.  
  5. import android.content.Context;
  6.  
  7. import android.database.Cursor;
  8.  
  9. import android.os.Bundle;
  10.  
  11. import android.widget.AlphabetIndexer;
  12.  
  13. import android.widget.ListView;
  14.  
  15. import android.widget.SectionIndexer;
  16.  
  17. import android.widget.SimpleCursorAdapter;
  18.  
  19.  
  20.  
  21. public class AlphabetIndexerActivity extends Activity {
  22.  
  23.     /** Called when the activity is first created. */
  24.  
  25.         ListView myListView;
  26.  
  27.         Cursor myCursor;
  28.  
  29.         String[] proj;
  30.  
  31.     @Override
  32.  
  33.     public void onCreate(Bundle savedInstanceState) {
  34.  
  35.         super.onCreate(savedInstanceState);
  36.  
  37.         setContentView(R.layout.main);
  38.  
  39.  
  40.  
  41.         DbUtil dbUtil=new DbUtil(getApplicationContext());
  42.  
  43.         dbUtil.open();
  44.  
  45.         dbUtil.insertRandomNames();
  46.  
  47.         myCursor=dbUtil.fetchAllData(); //getting my ordered cursor
  48.  
  49.        
  50.  
  51.         myListView=(ListView)findViewById(R.id.myListView);
  52.  
  53.         myListView.setFastScrollEnabled(true); //must be enabled
  54.  
  55.  
  56.  
  57.         myListView.setAdapter(
  58.  
  59.                        
  60.  
  61.                         new MyCursorAdapter(
  62.  
  63.                         getApplicationContext(),
  64.  
  65.                         android.R.layout.simple_list_item_1,
  66.  
  67.                         myCursor,
  68.  
  69.                         new String[]{DbUtil.KEY_NAME},//from
  70.  
  71.                         new int[]{android.R.id.text1}) //to
  72.  
  73.                
  74.  
  75.         );
  76.  
  77.        
  78.  
  79.         dbUtil.close();
  80.  
  81.        
  82.  
  83.        
  84.  
  85.     }
  86.  
  87.    
  88.  
  89.    
  90.  
  91.  
  92.  
  93.    
  94.  
  95.     class MyCursorAdapter extends SimpleCursorAdapter implements SectionIndexer{
  96.  
  97.  
  98.  
  99.         AlphabetIndexer alphaIndexer;
  100.  
  101.                 public MyCursorAdapter(Context context, int layout, Cursor c,
  102.  
  103.                                 String[] from, int[] to) {
  104.  
  105.                         super(context, layout, c, from, to);
  106.  
  107.                        
  108.  
  109. alphaIndexer=new AlphabetIndexer(c, myCursor.getColumnIndex(DbUtil.KEY_NAME), " ABCDEFGHIJKLMNOPQRSTUVWXYZ");
  110.  
  111.  
  112.  
  113. // you have just to instanciate the indexer class like this
  114.  
  115. //cursor,index of the sorted colum,a string representing the alphabeth (pay attention on the blank char at the beginning of the sequence)
  116.  
  117.                        
  118.  
  119.                        
  120.  
  121.                        
  122.  
  123.                 }
  124.  
  125.  
  126.  
  127.                 @Override
  128.  
  129.                 public int getPositionForSection(int section) {                
  130.  
  131.                         return alphaIndexer.getPositionForSection(section); //use the indexer
  132.  
  133.                 }
  134.  
  135.  
  136.  
  137.                 @Override
  138.  
  139.                 public int getSectionForPosition(int position) {                       
  140.  
  141.                         return alphaIndexer.getSectionForPosition(position); //use the indexer
  142.  
  143.                 }
  144.  
  145.  
  146.  
  147.                 @Override
  148.  
  149.                 public Object[] getSections() {
  150.  
  151.                         return alphaIndexer.getSections(); //use the indexer
  152.  
  153.                 }
  154.  
  155.        
  156.  
  157.     }
  158.  
  159.    
  160.  
  161.    
  162.  
  163.    
  164.  
  165. }
Parsed in 0.039 seconds, using GeSHi 1.0.8.4


enjoy :) !
Attachments
tut.png
tut.png (127.35 KiB) Viewed 27787 times
¯`·.¸¸.><((((º>¯`·.¸¸. ><((((º>
User avatar
qlimax
Master Developer
Master Developer
 
Posts: 271
Joined: Mon Aug 31, 2009 10:54 am
Location: Swiss

Top

Postby aminaz » Thu Jan 14, 2010 4:30 pm

Thnks qlimax for the tutorial it was so helpful
but i can't did this import android.widget. AlphabetIndexer; and SectionInder please help

Thanks a lot (F)
aminaz
Junior Developer
Junior Developer
 
Posts: 19
Joined: Thu Jan 07, 2010 5:07 pm

Postby qlimax » Thu Jan 14, 2010 4:42 pm

the sectionindexer interface and the alphabetIndexer class were introduced in android 1.5 -api level 3
you have to target your project to android 1.5 or higher to use it
¯`·.¸¸.><((((º>¯`·.¸¸. ><((((º>
User avatar
qlimax
Master Developer
Master Developer
 
Posts: 271
Joined: Mon Aug 31, 2009 10:54 am
Location: Swiss

SDK 1.6

Postby androidmate » Sun Jan 17, 2010 11:57 pm

Does this work on the 1.6 SDK? I have tried this code without success... :(
androidmate
Freshman
Freshman
 
Posts: 2
Joined: Sun Jan 17, 2010 11:55 pm

Postby qlimax » Mon Jan 18, 2010 6:45 pm

I tried it, targeting on the 1.6 sdk api level 4
and it works fine for me... :roll:

if you want, try to download the attached eclipse project
and let me know.

bye :wink:
Attachments
AlphabetInd.rar
(46.47 KiB) Downloaded 1079 times
¯`·.¸¸.><((((º>¯`·.¸¸. ><((((º>
User avatar
qlimax
Master Developer
Master Developer
 
Posts: 271
Joined: Mon Aug 31, 2009 10:54 am
Location: Swiss

Postby androidmate » Mon Jan 18, 2010 11:20 pm

Thanks for your help qlimax. I discovered that the reason my code wasn't working was because I didn't have enough rows in my database table. I inserted 200 records and it started working.
I think android cleverly decides not to show the thumb unless it really needs to.
androidmate
Freshman
Freshman
 
Posts: 2
Joined: Sun Jan 17, 2010 11:55 pm

Top

Postby qlimax » Mon Jan 18, 2010 11:22 pm

GOOD 8)
¯`·.¸¸.><((((º>¯`·.¸¸. ><((((º>
User avatar
qlimax
Master Developer
Master Developer
 
Posts: 271
Joined: Mon Aug 31, 2009 10:54 am
Location: Swiss

what about on itemcliklistener

Postby aminaz » Thu Jan 28, 2010 9:25 am

Good morning :)
is it the same because before i used another adapter and the oncliclistener isn't the same
if isn't what shall i define in that methode because i want to see on the clic the detail of any contact
Thnks
Have a nice day
aminaz
Junior Developer
Junior Developer
 
Posts: 19
Joined: Thu Jan 07, 2010 5:07 pm

:(

Postby aminaz » Fri Jan 29, 2010 12:57 pm

Please it's urgent and i need your help because i don't found any tutorial that speaks about this , please help
i repeat if i use this tutortial what can i do in the onitemclick because this new adapter is not the same as i usually use
Thnks a lot
aminaz
Junior Developer
Junior Developer
 
Posts: 19
Joined: Thu Jan 07, 2010 5:07 pm

Postby qlimax » Fri Jan 29, 2010 3:16 pm

sorry but I actually can't understand what's your problem.
If you post your code, it'll be faster and easier to find a solution

by the way, this adapter implements the setOnItemClickListener interface as well as any other adapter, so I don't see the problem.

bye
¯`·.¸¸.><((((º>¯`·.¸¸. ><((((º>
User avatar
qlimax
Master Developer
Master Developer
 
Posts: 271
Joined: Mon Aug 31, 2009 10:54 am
Location: Swiss

Postby aminaz » Tue Feb 02, 2010 11:40 am

myListView.setAdapter(

new MyCursorAdapter(
getApplicationContext(),
android.R.layout.simple_list_item_1,
myCursor,
new String[]{DbUtil.KEY_NAME,DbUtil.KEY_PHONE},//from
new int[]{android.R.id.text1,android.R.id.text2}) //to

);
I want to view the name of the person and his number i put this code but "FORCE CLOSE" and about setonitemclicklistener i will define it and i will give you the code later.
I have many problems with your code it works only with capital letters but i found the solution how to order them and the most imporatant problem that this code work only with your DbUtil WHY??????????

please i need the help of somebody i can give you the code but i'm confuesed now and i don't know where to begin...
Thnks for undrestanding and giving me the help
Bye
Thnks fo all
aminaz
Junior Developer
Junior Developer
 
Posts: 19
Joined: Thu Jan 07, 2010 5:07 pm

Postby qlimax » Tue Feb 02, 2010 4:04 pm

Try to post your code...(a zip of.your eclipse. Project )
I'll be happy to help you.
Bye
¯`·.¸¸.><((((º>¯`·.¸¸. ><((((º>
User avatar
qlimax
Master Developer
Master Developer
 
Posts: 271
Joined: Mon Aug 31, 2009 10:54 am
Location: Swiss

Postby aminaz » Tue Feb 02, 2010 4:42 pm

This is your code with some modification
:

the Database

/******************************/

package ch.egsolutions.alpha;

import java.util.Random;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;


public class DbUtil {



static final String KEY_ID="_id";
static final String KEY_NAME="name";
static final String KEY_PHONE="phone";


private static final String DB_NAME="tutorial";
private static final String TABLE_NAME="names";
private static final int DATABASE_VERSION = 1;

private static final String DATABASE_CREATE =
"create table "+TABLE_NAME+" ("+KEY_ID+" integer primary key autoincrement, "
+ KEY_NAME+" varchar not null,"+ KEY_PHONE+" varchar not null);";

private Context context;
private DatabaseHelper dbHelper;
private SQLiteDatabase db;


public DbUtil(Context context){
this.context=context;
this.dbHelper=new DatabaseHelper(this.context);
}

private static class DatabaseHelper extends SQLiteOpenHelper
{
DatabaseHelper(Context context)
{
super(context, DB_NAME, null, DATABASE_VERSION);
}

@Override
public void onCreate(SQLiteDatabase db)
{
db.execSQL(DATABASE_CREATE);
}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion,
int newVersion)
{
Log.v("DBUTIL", "Upgrading database from version " + oldVersion
+ " to "
+ newVersion + ", which will destroy all old data");
db.execSQL("DROP TABLE IF EXISTS "+TABLE_NAME);
onCreate(db);
}
}

public void open(){
db=dbHelper.getWritableDatabase();
}
public void close(){
dbHelper.close();
}



public void insertRandomNames(){
db.execSQL("DELETE FROM "+TABLE_NAME);
String s = "QWERTZUIOPASDFGHJKLYXCVBNM";
String s1 = "0123456789";
Random r = new Random();

ContentValues values=new ContentValues() ;
for(int i=0;i<200;i++){
values.clear();
values.put(KEY_NAME, s.substring(r.nextInt(s.length())));
values.put(KEY_PHONE, s1.substring(r.nextInt(s1.length())));
db.insert(TABLE_NAME, null, values);
}
}

public Cursor fetchAllData(){
return db.rawQuery("SELECT * FROM "+TABLE_NAME+" ORDER BY "+KEY_NAME+" ASC", null);
}

}

the Activity:

/****************************************/

package ch.egsolutions.alpha;
import android.app.Activity;
import android.content.Context;
import android.database.Cursor;
import android.os.Bundle;
import android.widget.AlphabetIndexer;
import android.widget.ListView;
import android.widget.SectionIndexer;
import android.widget.SimpleCursorAdapter;

public class AlphabetIndexerActivity extends Activity {
/** Called when the activity is first created. */
ListView myListView;
Cursor myCursor;
String[] proj;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

DbUtil dbUtil=new DbUtil(getApplicationContext());
dbUtil.open();
dbUtil.insertRandomNames();
myCursor=dbUtil.fetchAllData(); //getting my ordered cursor

myListView=(ListView)findViewById(R.id.myListView);
myListView.setFastScrollEnabled(true); //must be enabled

myListView.setAdapter(

new MyCursorAdapter(
getApplicationContext(),
android.R.layout.simple_list_item_1,
myCursor,
new String[]{DbUtil.KEY_NAME},//from
new int[]{android.R.id.text1}) //to

);
/* but i want to view the phone number and the name and why not some picture :) so i put this code but i have a force close:
myListView.setAdapter(

new MyCursorAdapter(
getApplicationContext(),
android.R.layout.simple_list_item_1,
myCursor,
new String[]{DbUtil.KEY_NAME,DbUtil.KEY_NAME},//from
new int[]{android.R.id.text1,android.R.id.text1}) //to

); */


dbUtil.close();


}




class MyCursorAdapter extends SimpleCursorAdapter implements SectionIndexer{

AlphabetIndexer alphaIndexer;
public MyCursorAdapter(Context context, int layout, Cursor c,
String[] from, int[] to) {
super(context, layout, c, from, to);

alphaIndexer=new AlphabetIndexer(c, myCursor.getColumnIndex(DbUtil.KEY_NAME), " ABCDEFGHIJKLMNOPQRSTUVWXYZ");

// you have just to instanciate the indexer class like this
//cursor,index of the sorted colum,a string representing the alphabeth (pay attention on the blank char at the beginning of the sequence)



}

@Override
public int getPositionForSection(int section) {
return alphaIndexer.getPositionForSection(section); //use the indexer
}

@Override
public int getSectionForPosition(int position) {
return alphaIndexer.getSectionForPosition(position); //use the indexer
}

@Override
public Object[] getSections() {
return alphaIndexer.getSections(); //use the indexer
}

}



}


that's all thanks :)))))
aminaz
Junior Developer
Junior Developer
 
Posts: 19
Joined: Thu Jan 07, 2010 5:07 pm

Postby qlimax » Tue Feb 02, 2010 10:38 pm

I would try to explain you:
you are trying to reference 2 textview in a layout that contains only one tv...

this layout: android.R.layout.simple_list_item_1
contains only a textview

new int[]{android.R.id.text1,android.R.id.text1}
2 textview here....-> force close :?

now:

try to do this:
define a layout describing your row... (with 2 tv i.e)


then set this adapter:

Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1. myListView.setAdapter(
  2.  
  3.  
  4.  
  5. new MyCursorAdapter(
  6.  
  7. getApplicationContext(),
  8.  
  9. R.layout.your_row_layout,
  10.  
  11. myCursor,
  12.  
  13. new String[]{DbUtil.KEY_NAME,DbUtil.KEY_NAME},//from
  14.  
  15. new int[]{R.id.tv1_in_your_layout,R.id.tv2_in_your_layout}) //to
  16.  
  17.  
  18.  
  19. );
Parsed in 0.034 seconds, using GeSHi 1.0.8.4



let me know...
bye
¯`·.¸¸.><((((º>¯`·.¸¸. ><((((º>
User avatar
qlimax
Master Developer
Master Developer
 
Posts: 271
Joined: Mon Aug 31, 2009 10:54 am
Location: Swiss

Need help on Indexer with Section

Postby iavian » Sun Mar 14, 2010 4:50 am

I need something like this with Index.

http://jsharkey.org/blog/2008/08/18/sep ... ndroid-09/


Thanks
iavian
Freshman
Freshman
 
Posts: 3
Joined: Sun Mar 14, 2010 4:48 am

Top
Next

Return to Advanced Tutorials

Who is online

Users browsing this forum: No registered users and 2 guests