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