完整代码
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;
/**
* ListView 实现点击侧边A-Z快速查找[中英文排序混排]
* @author Administrator
*
*/
public class LetterSideBar extends View {
OnTouchingLetterChangedListener onTouchingLetterChangedListener;
// 26个字母
public static String[] b = { "#", "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" };
int choose = -1;
Paint paint = new Paint();
public LetterSideBar(Context context) {
super(context);
}
public LetterSideBar(Context context, AttributeSet attrs) {
super(context, attrs);
}
public LetterSideBar(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
/**
* 重写这个方法
*/
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (showBkg) {
canvas.drawColor(Color.parseColor("#40000000"));
}
int height = getHeight();
int width = getWidth();
int singleHeight = height / b.length;
for (int i = 0; i < b.length; i++) {
paint.setColor(Color.BLACK);
// paint.setColor(Color.WHITE);
paint.setTypeface(Typeface.DEFAULT_BOLD);
// 抗锯齿
paint.setAntiAlias(true);
paint.setTextSize(20);
if (i == choose) {
paint.setColor(Color.parseColor("#3399ff"));
paint.setFakeBoldText(true);
}
float xPos = width / 2 - paint.measureText(b[i]) / 2;
float yPos = singleHeight * i + singleHeight;
canvas.drawText(b[i], xPos, yPos, paint);
paint.reset();
}
}
private boolean showBkg = false;
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
final int action = event.getAction();
final float y = event.getY();
final int oldChoose = choose;
final OnTouchingLetterChangedListener listener = onTouchingLetterChangedListener;
final int c = (int) (y / getHeight() * b.length);
switch (action) {
case MotionEvent.ACTION_DOWN:
showBkg = true;
if (oldChoose != c && listener != null) {
if (c > 0 && c < b.length) {
listener.onTouchingLetterChanged(b[c]);
choose = c;
invalidate();
}
}
break;
case MotionEvent.ACTION_MOVE:
if (oldChoose != c && listener != null) {
if (c > 0 && c < b.length) {
listener.onTouchingLetterChanged(b[c]);
choose = c;
invalidate();
}
}
break;
case MotionEvent.ACTION_UP:
showBkg = false;
choose = -1;
invalidate();
break;
}
return true;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
return super.onTouchEvent(event);
}
/**
* 向外公开的方法
*
* @param onTouchingLetterChangedListener
*/
public void setOnTouchingLetterChangedListener(
OnTouchingLetterChangedListener onTouchingLetterChangedListener) {
this.onTouchingLetterChangedListener = onTouchingLetterChangedListener;
}
public interface OnTouchingLetterChangedListener {
public void onTouchingLetterChanged(String s);
}
}
public class TestLetterSliderbarActivity extends Activity implements
OnTouchingLetterChangedListener {
private ListView lvShow;
private List<UserInfo> userInfos = new ArrayList<UserInfo>();
private TextView overlay;
private LetterSideBar myView;
private MyUserInfoAdapter adapter;
private OverlayThread overlayThread = new OverlayThread();
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.lletter_sliderbar);
lvShow = (ListView) findViewById(R.id.lvShow);
myView = (LetterSideBar) findViewById(R.id.lsb);
overlay = (TextView) findViewById(R.id.tvLetter);
lvShow.setTextFilterEnabled(true);
overlay.setVisibility(View.INVISIBLE);
getUserInfos();
Log.i("coder", "userInfos.size" + userInfos.size());
adapter = new MyUserInfoAdapter(this, userInfos);
lvShow.setAdapter(adapter);
myView.setOnTouchingLetterChangedListener(this);
}
private void getUserInfos() {
userInfos.clear();
userInfos.add(new UserInfo("唐僧", "18765432345", PinyinUtils
.getFirstSpell("唐僧")));
userInfos.add(new UserInfo("唐僧", "18765432345", PinyinUtils
.getFirstSpell("唐僧")));
userInfos.add(new UserInfo("猪师弟", "18765432345", PinyinUtils
.getFirstSpell("猪师弟")));
userInfos.add(new UserInfo("阿呆", "18765432345", PinyinUtils
.getFirstSpell("阿呆")));
userInfos.add(new UserInfo("8899", "18765432345", PinyinUtils
.getFirstSpell("8899")));
userInfos.add(new UserInfo("孙悟空", "18765432345", PinyinUtils
.getFirstSpell("孙悟空")));
userInfos.add(new UserInfo("阿三", "18765432345", PinyinUtils
.getFirstSpell("阿三")));
userInfos.add(new UserInfo("张三", "18765432345", PinyinUtils
.getFirstSpell("张三")));
userInfos.add(new UserInfo("张二B", "18876569008", PinyinUtils
.getFirstSpell("张二B")));
userInfos.add(new UserInfo("阿三", "18765432345", PinyinUtils
.getFirstSpell("阿三")));
userInfos.add(new UserInfo("张三", "18765432345", PinyinUtils
.getFirstSpell("张三")));
userInfos.add(new UserInfo("张二B", "18876569008", PinyinUtils
.getFirstSpell("张二B")));
userInfos.add(new UserInfo("阿三", "18765432345", PinyinUtils
.getFirstSpell("阿三")));
userInfos.add(new UserInfo("张三", "18765432345", PinyinUtils
.getFirstSpell("张三")));
userInfos.add(new UserInfo("张二B", "18876569008", PinyinUtils
.getFirstSpell("张二B")));
userInfos.add(new UserInfo("阿三", "18765432345", PinyinUtils
.getFirstSpell("阿三")));
userInfos.add(new UserInfo("张三", "18765432345", PinyinUtils
.getFirstSpell("张三")));
userInfos.add(new UserInfo("张二B", "18876569008", PinyinUtils
.getFirstSpell("张二B")));
userInfos.add(new UserInfo("李四", "18909876545", PinyinUtils
.getFirstSpell("李四")));
userInfos.add(new UserInfo("王小二", "18909876545", PinyinUtils
.getFirstSpell("王小二")));
userInfos.add(new UserInfo("张三丰", "18909876545", PinyinUtils
.getFirstSpell("张三丰")));
userInfos.add(new UserInfo("郭靖", "18909876545", PinyinUtils
.getFirstSpell("郭靖")));
ComparatorUser comparator = new ComparatorUser();
Collections.sort(userInfos, comparator);
}
private class ComparatorUser implements Comparator<UserInfo> {
@Override
public int compare(UserInfo lhs, UserInfo rhs) {
return compareStr(lhs.getPinyin(), rhs.getPhone());
}
private int compareStr(Object o1, Object o2) {
int length1 = ((String) o1).length();
int length2 = ((String) o2).length();
int length = length1 - length2 > 0 ? length2 : length1;
for (int i = 0; i < length; i++) {
char c1 = ((String) o1).charAt(i);
char c2 = ((String) o2).charAt(i);
String c1topinyin = concatPinyinStringArray(PinyinHelper
.toHanyuPinyinStringArray(c1));
String c2topinyin = concatPinyinStringArray(PinyinHelper
.toHanyuPinyinStringArray(c2));
if ("".equals(c1topinyin) && "".equals(c2topinyin)) {
if (c1 - c2 == 0) {
continue;
} else {
return c1 - c2;
}
} else if ("".equals(c1topinyin) && !"".equals(c2topinyin)) {
return -1;
} else if (!"".equals(c1topinyin) && "".equals(c2topinyin)) {
return 1;
} else {
int pinyinCompareValue = c1topinyin.compareTo(c2topinyin);
if (pinyinCompareValue == 0) {
if (c1 - c2 == 0) {
continue;
} else {
// ͬ���ְ��ʻ��Ƚ� �Ȳ�ʵ��
return c1 - c2;
}
}
return pinyinCompareValue;
}
}
return length1 - length2;
}
private String concatPinyinStringArray(String[] pinyinArray) {
StringBuffer pinyinStrBuf = new StringBuffer();
if ((null != pinyinArray) && (pinyinArray.length > 0)) {
for (int i = 0; i < pinyinArray.length; i++) {
pinyinStrBuf.append(pinyinArray[i]);
}
}
String outputString = pinyinStrBuf.toString();
return outputString;
}
}
private Handler handler = new Handler() {
};
private class OverlayThread implements Runnable {
public void run() {
overlay.setVisibility(View.GONE);
}
}
@Override
public void onTouchingLetterChanged(String s) {
Log.i("coder", "s:" + s);
overlay.setText(s);
overlay.setVisibility(View.VISIBLE);
handler.removeCallbacks(overlayThread);
handler.postDelayed(overlayThread, 1000);
if (alphaIndexer(s) > 0) {
int position = alphaIndexer(s);
Log.i("coder", "position:" + position);
lvShow.setSelection(position);
}
}
public int alphaIndexer(String s) {
int position = 0;
for (int i = 0; i < userInfos.size(); i++) {
if (userInfos.get(i).getPinyin().startsWith(s)) {
position = i;
break;
}
}
Log.i("coder", "i" + position + userInfos.get(position));
return position;
}
public class MyUserInfoAdapter extends BaseAdapter {
Context mContext;
List<UserInfo> userInfos;
public MyUserInfoAdapter(Context ctx, List<UserInfo> userInfos) {
// TODO Auto-generated constructor stub
this.mContext = ctx;
this.userInfos = userInfos;
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return userInfos.size();
}
@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return null;
}
@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return 0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
TextView tv;
if (convertView == null) { // if it's not recycled, initialize some
// attributes
tv = new TextView(mContext);
tv.setPadding(8, 8, 8, 8);
} else {
tv = (TextView) convertView;
}
tv.setText(userInfos.get(position).getName());
return tv;
}
}
public class UserInfo {
public String name;
public String phone;
public String pinyin;
public UserInfo(String name, String phone, String pinyin) {
this.name = name;
this.phone = phone;
this.pinyin = pinyin;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getPinyin() {
return pinyin;
}
public void setPinyin(String pinyin) {
this.pinyin = pinyin;
}
}
}
<?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="match_parent"
android:orientation="vertical" >
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView
android:id="@+id/lvShow"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</ListView>
<TextView
android:id="@+id/tvLetter"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:background="@color/gray"
android:gravity="center"
android:maxWidth="70dip"
android:minWidth="70dip"
android:padding="10dip"
android:textColor="#99FFFFFF"
android:textSize="50sp" />
<com.jasson.core.widgets.listview.LetterSideBar
android:id="@+id/lsb"
android:layout_height="wrap_content"
android:layout_width="30dip"
android:layout_gravity="right"/>
</FrameLayout>
</LinearLayout>