源代码下载:点击打开链接
1、制作显示定位字母的SideBar。实现方法:新建一个类继承View。
package com.example.sortedlist;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.TextView;
public class SideBar extends View{
// 触摸事件
private OnTouchingLetterChangedListener onTouchingLetterChangedListener;
private TextView mTextDialog;
public static String[] characters = { "A", "B", "C", "D", "E", "F", "G", "H", "I",
"J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V",
"W", "X", "Y", "Z", "#" };
public SideBar(Context context) {
super(context);
}
public SideBar(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public SideBar(Context context, AttributeSet attrs) {
super(context, attrs);
}
public void setTextView(TextView mTextDialog) {
this.mTextDialog = mTextDialog;
}
@SuppressLint("DrawAllocation")
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int width = getWidth(); // 获取对应宽度
int height = getHeight();// 获取对应高度
int singleHeight = height / characters.length; // 获取每一个字母的高
Paint paint = new Paint();
for(int i = 0; i < characters.length; i++){
paint.setTypeface(Typeface.DEFAULT_BOLD);
paint.setAntiAlias(true);
paint.setTextSize(12);
paint.setColor(Color.rgb(33, 65, 98));
float x = width / 2 - paint.measureText(characters[i]) / 2;
float y = singleHeight * (i + 1);
canvas.drawText(characters[i], x, y, paint);
paint.reset();
}
}
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
float y = event.getY();
int pos = (int) (y / getHeight() * characters.length);
switch (event.getAction()) {
case MotionEvent.ACTION_UP:
setBackgroundResource(R.drawable.sidebar);
mTextDialog.setVisibility(View.INVISIBLE);
break;
default:
setBackgroundResource(R.drawable.sidebar_hover);
if(pos >= 0 && pos <= characters.length){
if(onTouchingLetterChangedListener != null){
onTouchingLetterChangedListener.onTouchingLetterChanged(characters[pos]);
}
if(mTextDialog != null){
mTextDialog.setText(characters[pos]);
mTextDialog.setVisibility(View.VISIBLE);
}
}
break;
}
return true;
}
/**
* 向外公开的方法
* @param onTouchingLetterChangedListener
*/
public void setOnTouchingLetterChangedListener(OnTouchingLetterChangedListener onTouchingLetterChangedListener) {
this.onTouchingLetterChangedListener = onTouchingLetterChangedListener;
}
/**
* 接口
* @author coder
*/
public interface OnTouchingLetterChangedListener {
public void onTouchingLetterChanged(String s);
}
}
2、ListView Adapter实现
关键:判断getView方法中显示的View是否为属于的字母分类中的第一项,如果是第一项则显示导航字母TextView。
package com.example.sortedlist;
import java.util.Collections;
import java.util.List;
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 MyAdapter extends BaseAdapter{
LayoutInflater inflater;
List<Item> data;
public MyAdapter(Context context, List<Item> data){
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
this.data = data;
Collections.sort(this.data, new PinyinComparator()); //根据首字母进行排序
}
@Override
public int getCount() {
return data.size();
}
@Override
public Object getItem(int pos) {
return data.get(pos);
}
@Override
public long getItemId(int id) {
return id;
}
@Override
public View getView(int pos, View view, ViewGroup parent) {
ViewHolder holder = null;
if(view == null){
holder = new ViewHolder();
view = inflater.inflate(R.layout.listview_item, null);
holder.letterTV = (TextView) view.findViewById(R.id.letter);
holder.contentTV = (TextView) view.findViewById(R.id.content);
view.setTag(holder);
}
holder = (ViewHolder) view.getTag();
Item item = (Item) getItem(pos);
if(isFirst(item, pos)){
holder.letterTV.setVisibility(View.VISIBLE);
holder.letterTV.setText(item.getLetter());
holder.contentTV.setText(item.getContent());
}else{
holder.letterTV.setVisibility(View.GONE);
holder.contentTV.setText(item.getContent());
}
return view;
}
//判断当前Item是否为当前开头字母的第一个Item
public boolean isFirst(Item item, int position){
int pos = getFirstPosAtList(item.getLetter());
if(pos == position){
return true;
}
return false;
}
//获取data中首字母字母为letter的item的位置
public int getFirstPosAtList(String letter){
for(int i = 0; i < data.size(); i++){
Item item = data.get(i);
if(item.getLetter().equals(letter)){
return i;
}
}
return -1;
}
class ViewHolder{
TextView letterTV;
TextView contentTV;
}
}
MainActivity.java
package com.example.sortedlist;
import java.util.ArrayList;
import java.util.List;
import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.widget.ListView;
import android.widget.TextView;
import com.example.sortedlist.SideBar.OnTouchingLetterChangedListener;
public class MainActivity extends Activity {
private SideBar sideBar;
private TextView textView;
private ListView listView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
sideBar = (SideBar) this.findViewById(R.id.sidebar);
textView = (TextView) this.findViewById(R.id.label);
sideBar.setTextView(textView);
listView = (ListView) this.findViewById(R.id.listview);
//列表数据
List<String> data = new ArrayList<String>();
data.add("我");
data.add("喔");
data.add("你");
data.add("呢");
data.add("找");
data.add("白");
data.add("才");
data.add("嘛");
data.add("有");
data.add("啊");
//将列表数据封装成对象,包含需要排列字段的首字母
List<Item> items = filledData(data);
final MyAdapter adapter = new MyAdapter(getApplicationContext(), items);
listView.setAdapter(adapter);
//设置右侧触摸监听
sideBar.setOnTouchingLetterChangedListener(new OnTouchingLetterChangedListener() {
@Override
public void onTouchingLetterChanged(String s) {
//该字母首次出现的位置
int position = adapter.getFirstPosAtList(s);
if(position != -1){
listView.setSelection(position);
}
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
/**
* 为ListView填充数据(将列表数据封装成对象,包含需要排列字段的首字母)
* @param date
* @return
*/
private List<Item> filledData(List<String> data){
List<Item> mSortList = new ArrayList<Item>();
for(int i=0; i<data.size(); i++){
Item sortModel = new Item();
sortModel.setContent(data.get(i));
//汉字转换成拼音
String pinyin = CnToSpellUtils.getPinYin(data.get(i));
String sortString = pinyin.substring(0, 1).toUpperCase();
// 正则表达式,判断首字母是否是英文字母
if(sortString.matches("[A-Z]")){
sortModel.setLetter(sortString.toUpperCase());
}else{
sortModel.setLetter("#");
}
mSortList.add(sortModel);
}
return mSortList;
}
}