Sabe aquela funcionalidade da agenda de contatos do Android, onde quando se movimenta a barra de rolagem é exibida a primeira letra dos contatos atuais? Isso mesmo. Iremos aprender como implementá-la. Muito prático quando se deseja fornecer navegação rápida entre os itens de uma lista ordenada.

A navegação em listas no android pode se tornar muito cansativa quando se tem um número elevado de itens. Quando isso acontece, devemos fornecer alternativas ao usuário para facilitar esse acesso. Seja com filtros, barra de rolagem, carregamento parcial de dados, etc.
Caso a lista contenha dados que possam ser agrupados (por ordem alfabética, músicas por artista, etc.), uma boa opção é o uso da barra de rolagem com índices. Ela permite que se navegue rápidamente entre os itens. Abaixo iremos ver como implementar essa funcionalidade. No nosso caso será uma lista de artistas de rock, ordenadas por ordem alfabética.

Criando o Layout

1
2
3
4
5
6
7
8
9
10
11
12
13
<LinearLayout 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">
<ListView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:fastScrollEnabled="true"
android:fastScrollAlwaysVisible="true"
android:id="@+id/listView">
</ListView>
</LinearLayout>

No layout, para que nossa ListView exiba a barra de rolagem, é preciso definir android:fastScrollEnabled="true" e android:fastScrollAlwaysVisible="true".

android:fastScrollEnabled="true" habilita a exibição da barra de rolagem ao rolar a lista e android:fastScrollAlwaysVisible="true" faz com que a barra fique sempre visível.

Criando o Adapter

No Adapter é necessário implementar a interface SectionIndexer. Com ela a nossa lista poderá exibir os índices ao rolar:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
public class SectionListAdapter extends ArrayAdapter<String> implements SectionIndexer {
private HashMap<String,Integer> mapIndex;
private String[] sections;
private List<String> list;
public SectionListAdapter(Context c, List<String> list){
super(c,android.R.layout.simple_list_item_1,list);
this.list = list;
this.mapIndex = new HashMap<String,Integer>();
this.runIndex();
}
private void runIndex(){
for (int i = 0;i<list.size();i++){
String item = list.get(i);
String key = item.substring(0,1);
key = key.toUpperCase();
if(!mapIndex.containsKey(key)){
this.mapIndex.put(key,i);
}
Set<String> sectionLetters = mapIndex.keySet();
ArrayList<String> sectionList = new ArrayList<String>(sectionLetters);
Collections.sort(sectionList);
sections = new String[sectionList.size()];
sectionList.toArray(sections);
}
}
@Override
public Object[] getSections() {
return sections;
}
@Override
public int getPositionForSection(int section) {
return mapIndex.get(sections[section]);
}
@Override
public int getSectionForPosition(int i) {
return 0;
}
}

Primeiro precisamos realizar a indexação da nossa lista (método runIndex()). Nesse método, indexamos a primeira ocorrência de cada letra da lista em um HashMap (HashMap<letra,posicao>) e criamos um array com as seções: A,B,C,D,…
Logo após implementamos os três métodos da interface: getSections(),getPositionForSection(int section) e getSectionForPosition(int i).

Iniciando a ListView

Agora iremos inicializar a nossa lista:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
public class MainActivity extends AppCompatActivity {
public static final String[] bands={"AC/DC","Adam and the Ants","Aerosmith","Afrika Bambaataa",
"Al Foster","Al Green","Alan Parsons","Alice Cooper","Amy Winehouse","Animals","Annie Lennox",
"Arctic Monkeys","Atmosphere","Audioslave","Babyshambles","Bat For Lashes","Bauhaus",
"BB King","Beastie Boys","Beck","Beyonce"
,"Biffy Clyro","Bob Dylan","Bob Marley","Boomtown Rats","Brian Wilson","Bruce Springsteen",
"Chic","Chris Isaak","Chuck Berry","Cliff Richard","Cliff Richard and the Shadows","Coldplay",
"Cranberries","David Bowie","Don Williams","Dr. Feelgood","Duffy","Duke Ellington","Elton John",
"Elvis Costello","Elvis Presley","Eric Clapton","Florence and the Machine","Foo Fighters",
"Frank Sinatra","Grace Jones","Green Day","Guns n Roses","Happy Mondays","Herbie Hancock",
"Horace Silver","Hugh Masekela","Humble Pie","Ian Brown","Ian Dury","Ian McCulloch","Iggy Pop",
"Jackson Scott","James Brown","Janis Joplin","Jimi Hendrix","Jimmy Rushing","Joe Strummer",
"John Lennon","John Lydon","Johnny Borrell","Johnny Cash", "Kaiser Cheifs",
"Kings of Leon", "Kiss","Lady Gaga","Led Zeppelin","Lee 'Scratch' Perry","Lenny Kravitz",
"Libertines","Lily Allen","Louis Armstrong","Madness","Madonna","Manic Street Preachers",
"Marilyn Manson","Marvin Gaye","Metallica","Michael Jackson","Motorhead","My Chemical Romance",
"Neil Young","Nick Cave","Nigel Kennedy","Nina Simone","Nirvana","Noisettes","Oasis",
"Offspring","Ozzy Osbourne", "Paul McCartney","Paul Simon","Paul Weller","Pearl Jam",
"Pendulum","Performance Boxset","Pete Burns","Pete Doherty","Pete Townshend","Peter Gabriel",
"Pink Floyd","Prince","Queen","Radiohead","Razorlight","Red Hot Chili Peppers",
"REM","Richard Ashcroft","Scissor Sisters","Sex Pistols","The Beatles","The Cure",
"The Doors","The Killers","The Pet Shop Boys","The Police","The Pretenders","The Ramones",
"The Revillos","The Rolling Stones","The Tourists","The Undertones","The Who","Tina Turner",
"Toots and the Maytals","Trevor Moss and Hannah Lou","TV on the Radio","U2","Van Morrison",
"Velvet Revolver","White Stripes","Wishbone Ash","Wreckless Eric","Wu-Tang Clan","Yoko Ono",
"Yumi Matsutoya"
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ListView listViewItems = (ListView) this.findViewById(R.id.listView);
List<String> bandList = Arrays.asList(bands);
Collections.sort(bandList);
listViewItems.setAdapter(new SectionListAdapter(this,bandList));
}
}

Instanciamos o nosso adapter com a lista de nomes e o setamos na ListView. Rodando o projeto, iremos obter o seguinte resultado:

ScrollSection

O código completo desse exemplo pode ser encontrado aqui: GitHub

Espero que vocês possam utilizar essa funcionalidade nos seus projetos e usufruir dessa facilidade de navegação.
E caso surjam dúvidas ou sugestões, é só deixar o seu comentário. ^^
Até mais.