activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView
android:id="@+id/listview"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</ListView>
<com.atguigu.quickindex.QuickIndexBar
android:id="@+id/qucikIndexBar"
android:layout_width="35dp"
android:layout_height="match_parent"
android:layout_alignParentRight="true"
android:background="#CFCFCF" />
<TextView
android:id="@+id/currentIndex"
android:layout_width="120dp"
android:layout_height="105dp"
android:layout_centerInParent="true"
android:background="@drawable/bg_index"
android:gravity="center"
android:text="A"
android:textColor="#ffffff"
android:textSize="30sp"
android:visibility="gone" />
</RelativeLayout><?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<TextView
android:id="@+id/index"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="5dp"
android:paddingBottom="5dp"
android:paddingLeft="10dp"
android:text="A"
android:textColor="#ffffff"
android:background="#666666"
android:textSize="18sp"/>
<TextView
android:id="@+id/name"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:padding="10dp"
android:text="adasd"
android:textColor="#666666"
android:textSize="20sp"/>
</LinearLayout>package com.atguigu.quickindex;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;
import com.atguigu.quickindex.QuickIndexBar.OnTouchIndexChange;
public class MainActivity extends Activity {
private ListView listView;
private QuickIndexBar qucikIndexBar;
private TextView currentIndex;
// 数据集合
private List<Friend> friends = new ArrayList<Friend>();
// 适配器
private FriendAdapter adapter;
private Handler handler = new Handler();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 加载主布局
setContentView(R.layout.activity_main);
// 初始化控件
init();
}
private void init() {
/** 初始化布局视图 */
listView = (ListView) findViewById(R.id.listview);
qucikIndexBar = (QuickIndexBar) findViewById(R.id.qucikIndexBar);
currentIndex = (TextView) findViewById(R.id.currentIndex);
/** 初始化数据 */
initData();
// 创建适配器
adapter = new FriendAdapter();
// 设置适配器
listView.setAdapter(adapter);
// 设置触摸的字母变化的监听
qucikIndexBar.setOnTouchIndexChange(new OnTouchIndexChange() {
@Override
public void onChange(String word) {// word为当前触摸的字母
// 显示当前触摸的字母
showInexWord(word);
// 使用列表定位到对应的列表项
locationWord(word);
}
});
}
private void locationWord(String word) {
for (int i = 0; i < friends.size(); i++) {
//名字首字母
String firstWord = friends.get(i).getPinyin().charAt(0) + "";
if (firstWord.equals(word)) {
//定位到item的位置
listView.setSelection(i);
return;
}
}
}
private void showInexWord(String word) {
currentIndex.setVisibility(View.VISIBLE);
currentIndex.setText(word);
//停掉所用handler的消息,防止内存泄露
handler.removeCallbacksAndMessages(null);
//2秒的定时器
handler.postDelayed(new Runnable() {
@Override
public void run() {
currentIndex.setVisibility(View.GONE);
}
}, 2000);
}
private void initData() {
// 虚拟数据
friends.add(new Friend("张晓飞"));
friends.add(new Friend("杨光福"));
friends.add(new Friend("胡继群"));
friends.add(new Friend("刘畅"));
friends.add(new Friend("钟泽兴"));
friends.add(new Friend("尹革新"));
friends.add(new Friend("安传鑫"));
friends.add(new Friend("张骞壬"));
friends.add(new Friend("温松"));
friends.add(new Friend("李凤秋"));
friends.add(new Friend("刘甫"));
friends.add(new Friend("娄全超"));
friends.add(new Friend("张猛"));
friends.add(new Friend("王英杰"));
friends.add(new Friend("李振南"));
friends.add(new Friend("孙仁政"));
friends.add(new Friend("唐春雷"));
friends.add(new Friend("牛鹏伟"));
friends.add(new Friend("姜宇航"));
friends.add(new Friend("刘挺"));
friends.add(new Friend("张洪瑞"));
friends.add(new Friend("张建忠"));
friends.add(new Friend("侯亚帅"));
friends.add(new Friend("刘帅"));
friends.add(new Friend("乔竞飞"));
friends.add(new Friend("徐雨健"));
friends.add(new Friend("吴亮"));
friends.add(new Friend("王兆霖"));
friends.add(new Friend("阿三"));
friends.add(new Friend("二毛"));
/**
* Comparable。可以让自定义对象实现一个Comparable接口,这个接口只有一个方法comparableTo(Object o)
*
* 其规则是当前对象与o对象进行比较,返回一个int值,系统根据此值进行排序。
*
* 如当前对象>o对象,则返回值>0;
*
* 如当前对象=o对象,则返回值=0;
*
* 如当前对象<o对象,则返回值<0;
*/
Collections.sort(friends);
}
/**
* adapter
*/
class FriendAdapter extends BaseAdapter {
@Override
public int getCount() {
return friends.size();
}
@Override
public Object getItem(int position) {
return friends.get(position);
}
@Override
public long getItemId(int position) {
return 0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
if (convertView == null) {
convertView = View.inflate(getApplicationContext(),
R.layout.item_friend, null);
holder = new ViewHolder();
holder.index = (TextView) convertView.findViewById(R.id.index);
holder.name = (TextView) convertView.findViewById(R.id.name);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
Friend friend = friends.get(position);
String firstWord = friend.getPinyin().charAt(0) + "";// 得到拼音首字母
if (position == 0) {// 如果是第一个, 显示首字母View
holder.index.setVisibility(View.VISIBLE);
} else {// 如果不是第一个
// 上一项的拼音首字母
String preFirstWord = friends.get(position - 1).getPinyin()
.charAt(0)
+ "";
if (firstWord.equals(preFirstWord)) {// 如果当前的与上一个相同, 不显示首字母View
holder.index.setVisibility(View.GONE);
} else {// 否则, 显示
holder.index.setVisibility(View.VISIBLE);
}
}
holder.index.setText(firstWord);
holder.name.setText(friend.getName());
return convertView;
}
class ViewHolder {
TextView index, name;
}
}
}
package com.atguigu.quickindex;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
/**
* 自定义快速索引的View
*/
public class QuickIndexBar extends View {
public QuickIndexBar(Context context, AttributeSet attrs) {
super(context, attrs);
// 初始化paint
paint = new Paint();
paint.setAntiAlias(true);// 抗据齿
}
private Paint paint;
// 字母的宽、高
private int cellWidth;
private int cellHeight;
private int touchIndex = -1;
// 字体选中、非选中大小
private int textSize;
private int textTouchSize;
private String[] indexArr = { "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" };
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
cellWidth = this.getMeasuredWidth();
cellHeight = this.getMeasuredHeight() / indexArr.length;
textSize = cellHeight - 5;
textTouchSize = cellHeight + 5;
}
@SuppressLint("DrawAllocation")
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
for (int i = 0; i < indexArr.length; i++) {
// 字母的字体大小
paint.setTextSize(i == touchIndex ? textTouchSize : textSize);
// 字母的字体颜色
paint.setColor(i == touchIndex ? Color.parseColor("#666666")
: Color.WHITE);
// 计算字母显示的宽高
Rect bounds = new Rect();
//paint.getTextBounds(str, 0, str.length(), rect);
paint.getTextBounds(indexArr[i], 0, 1, bounds);
int width = bounds.width();
int height = bounds.height();
// 计算字母绘制的坐标
float x = cellWidth / 2 - width / 2;
float y = i * cellHeight + cellHeight / 2 + height / 2;
// 绘制字母文本
canvas.drawText(indexArr[i], x, y, paint);
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
// 相对于当前View的事件y坐标
int y = (int) event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_MOVE:
// 如果没有在当前字母的区域内, 就需要更新touchIndex, 并重绘
int index = y / cellHeight;
if (index != touchIndex) {
touchIndex = index;
if (touchIndex >= indexArr.length)
touchIndex = indexArr.length - 1;
// 强制重绘
invalidate();
// 如果有监听器, 调用监听器的回调方法
if (onTouchIndexChange != null) {
onTouchIndexChange.onChange(indexArr[touchIndex]);
}
}
break;
case MotionEvent.ACTION_UP:
touchIndex = -1;
// 强制重绘
invalidate();
break;
default:
break;
}
return true;
}
private OnTouchIndexChange onTouchIndexChange;
public void setOnTouchIndexChange(OnTouchIndexChange onTouchIndexChange) {
this.onTouchIndexChange = onTouchIndexChange;
}
public interface OnTouchIndexChange {
public void onChange(String word);
}
}
package com.atguigu.quickindex;
/**
* 好友信息对象
*/
public class Friend implements Comparable<Friend> {
private String name;//姓名
private String pinyin;//姓名对应的拼音
public Friend(String name) {
super();
this.name = name;
//通过名字得到对应的拼音
this.pinyin = PinYinUtils.getPinYin(name);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPinyin() {
return pinyin;
}
public void setPinyin(String pinyin) {
this.pinyin = pinyin;
}
@Override
public String toString() {
return "Friend [name=" + name + ", pinyin=" + pinyin + "]";
}
/**
* 此接口强行对实现它的每个类的对象进行整体排序。此排序被称为该类的自然排序 ,类的 compareTo 方法被称为它的自然比较方法 。
*/
@Override
public int compareTo(Friend another) {
return pinyin.compareTo(another.getPinyin());
}
}
package com.atguigu.quickindex;
import net.sourceforge.pinyin4j.PinyinHelper;
import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType;
import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat;
import net.sourceforge.pinyin4j.format.HanyuPinyinToneType;
import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination;
/**
* 将汉字转换为拼音
*/
public class PinYinUtils {
/**
* 得到指定汉字的拼音
* 注意:不应该被频繁调用,它消耗一定内存
*/
public static String getPinYin(String hanzi){
String pinyin = "";
HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat();//控制转换是否大小写,是否带音标
format.setCaseType(HanyuPinyinCaseType.UPPERCASE);//大写
format.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
//由于不能直接对多个汉字转换,只能对单个汉字转换
char[] arr = hanzi.toCharArray();
for (int i = 0; i < arr.length; i++) {
if(Character.isWhitespace(arr[i]))continue;//如果是空格,则不处理,进行下次遍历
//汉字是2个字节存储,肯定大于127,所以大于127就可以当为汉字转换
if(arr[i]>127){
try {
//由于多音字的存在,单 dan shan
String[] pinyinArr = PinyinHelper.toHanyuPinyinStringArray(arr[i], format);
if(pinyinArr!=null){
pinyin += pinyinArr[0];
}else {
pinyin += arr[i];
}
} catch (BadHanyuPinyinOutputFormatCombination e) {
e.printStackTrace();
//不是正确的汉字
pinyin += arr[i];
}
}else {
//不是汉字,
pinyin += arr[i];
}
}
return pinyin;
}
}
原文地址:http://blog.csdn.net/u013210620/article/details/46380683