原文:http://androidopentutorials.com/android-listview-fastscroll/
In this Android example, we will see how to create a ListView with fast scroll enabled.
Project Description:
This Android ListView tutorial explains the following,
- How to create a ListView which displays a list of items (in our example we display a list of fruits).
- How to enable fast scroll in ListView
- How to customize fast scroll style attributes such as,
- Fast scroll thumb drawable
- Fast scroll text color
- Fast scroll track drawable
- Fast scroll preview background
You can use this site http://www.android-holo-colors.com/ to generate drawables and themes which you can copy into your project.
Download “Android ListView FastScroll” AndroidFastScrollDemo.zip – Downloaded 4 times – 1 MB
Android Project
Create a new Android project and name it as “ AndroidFastScrollDemo “.
Resources
colors.xml
Create a new file res/values/colors.xml and copy paste the following content.
<?xml version="1.0" encoding="utf-8"?> <resources> <color name="apptheme_color">#DA4A38</color> </resources>
<? xml version = "1.0" encoding = "utf-8" ?>
< resources >
< color name = "apptheme_color" > #DA4A38</color>
< / resources >
|
strings.xml
Open res/values/strings.xml and edit to have the content as shown below.
<?xml version="1.0" encoding="utf-8"?> <resources> <string name="app_name">AndroidFastScrollDemo</string> <string name="action_settings">Settings</string> <string name="hello_world">Hello world!</string> <string-array name="fruits_array"> <item>Apples</item> <item>Apricots</item> <item>Avocado</item> <item>Annona</item> <item>Banana</item> <item>Bilberry</item> <item>Blackberry</item> <item>Custard Apple</item> <item>Clementine</item> <item>Cantalope</item> <item>Coconut</item> <item>Currant</item> <item>Cherry</item> <item>Cherimoya</item> <item>Date</item> <item>Damson</item> <item>Durian</item> <item>Elderberry</item> <item>Fig</item> <item>Feijoa</item> <item>Grapefruit</item> <item>Grape</item> <item>Gooseberry</item> <item>Guava</item> <item>Honeydew melon</item> <item>Huckleberry</item> <item>Jackfruit</item> <item>Juniper Berry</item> <item>Jambul</item> <item>Jujube</item> <item>Kiwi</item> <item>Kumquat</item> <item>Lemons</item> <item>Limes</item> <item>Lychee</item> <item>Mango</item> <item>Mandarin</item> <item>Mangostine</item> <item>Nectaraine</item> <item>Orange</item> <item>Olive</item> <item>Prunes</item> <item>Pears</item> <item>Plum</item> <item>Pineapple</item> <item>Peach</item> <item>Papaya</item> <item>Passionfruit</item> <item>Pomegranate</item> <item>Pomelo</item> <item>Raspberries</item> <item>Rock melon</item> <item>Rambutan</item> <item>Strawberries</item> <item>Sweety</item> <item>Salmonberry</item> <item>Satsuma</item> <item>Tangerines</item> <item>Tomato</item> <item>Ugli</item> <item>Watermelon</item> <item>Woodapple</item> </string-array> </resources>
<? xml version = "1.0" encoding = "utf-8" ?>
< resources >
< string name = "app_name" > AndroidFastScrollDemo < / string > < string name = "action_settings" > Settings < / string > < string name = "hello_world" > Hello world ! < / string > < string - array name = "fruits_array" > < item > Apples < / item > < item > Apricots < / item > < item > Avocado < / item > < item > Annona < / item > < item > Banana < / item > < item > Bilberry < / item > < item > Blackberry < / item > < item > Custard Apple < / item > < item > Clementine < / item > < item > Cantalope < / item > < item > Coconut < / item > < item > Currant < / item > < item > Cherry < / item > < item > Cherimoya < / item > < item > Date < / item > < item > Damson < / item > < item > Durian < / item > < item > Elderberry < / item > < item > Fig < / item > < item > Feijoa < / item > < item > Grapefruit < / item > < item > Grape < / item > < item > Gooseberry < / item > < item > Guava < / item > < item > Honeydew melon < / item > < item > Huckleberry < / item > < item > Jackfruit < / item > < item > Juniper Berry < / item > < item > Jambul < / item > < item > Jujube < / item > < item > Kiwi < / item > < item > Kumquat < / item > < item > Lemons < / item > < item > Limes < / item > < item > Lychee < / item > < item > Mango < / item > < item > Mandarin < / item > < item > Mangostine < / item > < item > Nectaraine < / item > < item > Orange < / item > < item > Olive < / item > < item > Prunes < / item > < item > Pears < / item > < item > Plum < / item > < item > Pineapple < / item > < item > Peach < / item > < item > Papaya < / item > < item > Passionfruit < / item > < item > Pomegranate < / item > < item > Pomelo < / item > < item > Raspberries < / item > < item > Rock melon < / item > < item > Rambutan < / item > < item > Strawberries < / item > < item > Sweety < / item > < item > Salmonberry < / item > < item > Satsuma < / item > < item > Tangerines < / item > < item > Tomato < / item > < item > Ugli < / item > < item > Watermelon < / item > < item > Woodapple < / item > < / string - array >
< / resources >
|
Layout files
activity_main.xml
This XML layout file ( activity_main.xml ) is used to define ListView
Open activity_main.xml file in res/layout and copy the following content.
<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:padding="5dp" tools:context=".MainActivity" > <ListView android:id="@android:id/list" android:layout_width="fill_parent" android:layout_height="fill_parent" android:scrollbarStyle="outsideOverlay" /> </RelativeLayout>
< 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 : padding = "5dp" tools : context = ".MainActivity" >
< ListView
android : id = "@android:id/list" android : layout_width = "fill_parent" android : layout_height = "fill_parent" android : scrollbarStyle = "outsideOverlay" / > < / RelativeLayout > |
list_item.xml
This XML layout file ( list_item.xml ) is used for displaying a particular ListView item. It contains a single TextView.
Create a new list_item.xml file in res/layout and copy the following content.
<?xml version="1.0" encoding="utf-8"?> <TextView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/txt_title" android:layout_width="fill_parent" android:layout_height="fill_parent" android:paddingBottom="10dp" android:paddingLeft="15dp" android:paddingTop="10dp" />
<? xml version = "1.0" encoding = "utf-8" ?> < TextView xmlns : android = "http://schemas.android.com/apk/res/android" android : id = "@+id/txt_title" android : layout_width = "fill_parent" android : layout_height = "fill_parent" android : paddingBottom = "10dp" android : paddingLeft = "15dp" android : paddingTop = "10dp" / > |
styles.xml
Open res/values/styles.xml and edit to have the content as shown below. Here, fast scroll style attributes are defined.
<resources> <style name="AppBaseTheme" parent="android:Theme.Light"> </style> <style name="AppTheme" parent="AppBaseTheme"> <item name="android:fastScrollThumbDrawable">@drawable/fastscroll_thumb_holo</item> <item name="android:fastScrollOverlayPosition">atThumb</item> <item name="android:fastScrollTextColor">@color/apptheme_color</item> <item name="android:fastScrollTrackDrawable">@drawable/fastscroll_thumb_pressed_holo</item> <item name="android:fastScrollPreviewBackgroundRight">@drawable/bg_default_focused_holo_light</item> </style> </resources>
< resources >
<style name ="AppBaseTheme" parent ="android : Theme.Light">
</style>
<style name ="AppTheme" parent ="AppBaseTheme"> <item name ="android : fastScrollThumbDrawable">@drawable/fastscroll_thumb_holo</item> <item name ="android : fastScrollOverlayPosition">atThumb</item> <item name ="android : fastScrollTextColor">@color/apptheme_color</item> <item name ="android : fastScrollTrackDrawable">@drawable/fastscroll_thumb_pressed_holo</item> <item name ="android : fastScrollPreviewBackgroundRight">@drawable/bg_default_focused_holo_light</item>
</style>
< / resources >
|
fastscroll_thumb_holo.xml
Create a new file fastscroll_thumb_holo.xml in res/drawable/ and copy the following content. It defines selector for fast scroll thumb for default and pressed states.
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:drawable="@drawable/fastscroll_thumb_pressed_holo" android:state_pressed="true"/> <item android:drawable="@drawable/fastscroll_thumb_default_holo"/> </selector>
<? xml version = "1.0" encoding = "utf-8" ?> < selector xmlns : android = "http://schemas.android.com/apk/res/android" > < item android : drawable = "@drawable/fastscroll_thumb_pressed_holo" android: state_pressed = "true" / > < item android : drawable = "@drawable/fastscroll_thumb_default_holo" / >
< / selector >
|
Source files
ListAdapter class
Create a new class “ ListAdapter ” in the package com.androidopentutorials.fastscrolldemo.adapter .
- This is the custom ListView adapter class which implements SectionIndexer to enable fast scrolling between sections of an AbsListView. A section is a group of list items that have something in common. For example, they may begin with the same letter or they may be songs from the same artist. SectionIndexer provides following methods,
getPositionForSection(int section) returns the starting (first) position of that section with the list adapter |
getSectionForPosition(int position) returns the index of the corresponding section within the array of section objects in that given position |
getSections() returns an array of objects representing sections of the list. |
package com.androidopentutorials.fastscrolldemo.adapter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import android.content.Context;
import android.util.Log;
import android.widget.ArrayAdapter;
import android.widget.SectionIndexer;
import com.androidopentutorials.fastscrolldemo.R;
public class ListAdapter extends ArrayAdapter<String> implements SectionIndexer {
HashMap<String, Integer> mapIndex;
String[] sections;
List<String> fruits;
public ListAdapter(Context context, List<String> fruitList) {
super(context, R.layout.list_item, fruitList);
this.fruits = fruitList;
mapIndex = new LinkedHashMap<String, Integer>();
for (int x = 0; x < fruits.size(); x++) {
String fruit = fruits.get(x);
String ch = fruit.substring(0, 1);
ch = ch.toUpperCase(Locale.US);
// HashMap will prevent duplicates
mapIndex.put(ch, x);
}
Set<String> sectionLetters = mapIndex.keySet();
// create a list from the set to sort
ArrayList<String> sectionList = new ArrayList<String>(sectionLetters);
Log.d("sectionList", sectionList.toString());
Collections.sort(sectionList);
sections = new String[sectionList.size()];
sectionList.toArray(sections);
}
public int getPositionForSection(int section) {
Log.d("section", "" + section);
return mapIndex.get(sections[section]);
}
public int getSectionForPosition(int position) {
Log.d("position", "" + position);
return 0;
}
public Object[] getSections() {
return sections;
}
}
package com . androidopentutorials . fastscrolldemo . adapter ; import java . util . ArrayList ; import java . util . Collections ; import java . util . HashMap ; import java . util . LinkedHashMap ; import java . util . List ; import java . util . Locale ; import java . util . Set ; import android . content . Context ; import android . util . Log ; import android . widget . ArrayAdapter ; import android . widget . SectionIndexer ; import com . androidopentutorials . fastscrolldemo . R ; public class ListAdapter extends ArrayAdapter < String > implements SectionIndexer{ HashMap < String , Integer > mapIndex ; String [ ] sections ; List < String > fruits ; public ListAdapter ( Context context , List < String > fruitList ) { super ( context , R . layout . list_item , fruitList ) ; this . fruits = fruitList ; mapIndex = new LinkedHashMap < String , Integer > ( ) ; for ( int x = 0 ; x < fruits . size ( ) ; x ++ ) { String fruit = fruits . get ( x ) ; String ch = fruit . substring ( 0 , 1 ) ; ch = ch . toUpperCase ( Locale . US ) ; // HashMap will prevent duplicates mapIndex . put ( ch , x ) ;
}
Set < String > sectionLetters = mapIndex . keySet ( ) ; // create a list from the set to sort ArrayList < String > sectionList = new ArrayList < String > ( sectionLetters ) ; Log . d ( "sectionList" , sectionList . toString ( ) ) ; Collections . sort ( sectionList ) ; sections = new String [ sectionList . size ( ) ] ; sectionList . toArray ( sections ) ;
}
public int getPositionForSection ( int section ) { Log . d ( "section" , "" + section ) ; return mapIndex . get ( sections [ section ] ) ;
}
public int getSectionForPosition ( int position ) { Log . d ( "position" , "" + position ) ; return 0 ;
}
public Object [ ] getSections ( ) { return sections ;
}
}
|
Understanding getPositionForSection(section) and getSectionForPosition(position)
For example if the index of section B is 1 and the indexed column of the cursor has the following data
Position | Data | getSectionForPosition(position) |
---|---|---|
0 | Annona | 0 |
1 | Apples | 0 |
2 | Apricots | 0 |
3 | Avocado | 0 |
4 | Banana | 1 |
5 | Bilberry | 1 |
6 | Blackberry | 1 |
7 | Cantalope | 2 |
- getPositionForSection(0) – returns 0
- getPositionForSection(1) – returns 4
- getPositionForSection(2) – returns 7
MainActivity
This is the main activity class. To enable fast scroll in ListView, do the following steps,
- Set fast scroll mode to your ListView
- listViewInstance.setFastScrollEnabled(true);
- Make your adapter implement android.widget.SectionIndexer interface and override the methods to see an alphabet letter on which you are currently on during fast scrolling.
package com.androidopentutorials.fastscrolldemo;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import android.app.ListActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;
import android.widget.Toast;
import com.androidopentutorials.fastscrolldemo.adapter.ListAdapter;
public class MainActivity extends ListActivity {
ListView fruitView;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
fruitView = (ListView) findViewById(android.R.id.list);
fruitView.setFastScrollEnabled(true);
String[] fruits = getResources().getStringArray(R.array.fruits_array);
List<String> fruitList = Arrays.asList(fruits);
Collections.sort(fruitList);
setListAdapter(new ListAdapter(this, fruitList));
fruitView.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View arg1,
int position, long arg3) {
Toast.makeText(getApplicationContext(),
"" + parent.getItemAtPosition(position),
Toast.LENGTH_LONG).show();
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
package com . androidopentutorials . fastscrolldemo ; import java . util . Arrays ; import java . util . Collections ; import java . util . List ; import android . app . ListActivity ; import android . os . Bundle ; import android . view . Menu ; import android . view . View ; import android . widget . AdapterView ; import android . widget . AdapterView . OnItemClickListener ; import android . widget . ListView ; import android . widget . Toast ; import com . androidopentutorials . fastscrolldemo . adapter . ListAdapter ; public class MainActivity extends ListActivity { ListView fruitView ;
@ Override
public void onCreate ( Bundle savedInstanceState ) { super . onCreate ( savedInstanceState ) ; setContentView ( R . layout . activity_main ) ; fruitView = ( ListView ) findViewById ( android . R . id . list ) ; fruitView . setFastScrollEnabled ( true ) ; String [ ] fruits = getResources ( ) . getStringArray ( R . array . fruits_array ) ; List < String > fruitList = Arrays . asList ( fruits ) ; Collections . sort ( fruitList ) ; setListAdapter ( new ListAdapter ( this , fruitList ) ) ; fruitView . setOnItemClickListener ( new OnItemClickListener ( ) { public void onItemClick ( AdapterView < ? > parent , View arg1 , int position , long arg3 ) { Toast . makeText ( getApplicationContext ( ) , "" + parent . getItemAtPosition ( position ) , Toast . LENGTH_LONG ) . show ( ) ;
}
} ) ;
}
@ Override
public boolean onCreateOptionsMenu ( Menu menu ) { getMenuInflater ( ) . inflate ( R . menu . main , menu ) ; return true ;
}
}
|
- The string array is retrieved from strings.xml. We create an instance of ListAdapter which implements SectionIndexer and set this to the ListView.
Output
Running the app will display the following output.