这个功能也经常用到比如:微信好友列表, 联系人通讯录, 应用管理, 文件管理等
效果图:
实现步骤:
- 绘制 A-Z.的索引,处理Touch事件
- 根据回调回调显示当前索引
- 汉字转换成拼音,将数据进行分组
- 在ListView中使用自定义控件
自定义View代码:
public class QuickIndexView extends View {
int touchIndex = -1;
private static final String[] LETTERS = new String[]{
"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"};
private Paint mPaint;
private int cellWidth;
private float cellHeight;
private OnLetterIndexChangeListener mLetterIndexChangeListener;
public interface OnLetterIndexChangeListener {
void onLetterIndexChange(String letter);
}
public void setOnLetterIndexChangeListener(OnLetterIndexChangeListener mLetterIndexChangeListener) {
this.mLetterIndexChangeListener = mLetterIndexChangeListener;
}
public QuickIndexView(Context context) {
this(context, null);
}
public QuickIndexView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public QuickIndexView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
// Paint.ANTI_ALIAS_FLAG 字体抗锯齿
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setColor(Color.GRAY);
// 粗体
mPaint.setTypeface(Typeface.DEFAULT_BOLD);
mPaint.setTextSize(DensityUtils.dp2px(getContext(), 12));
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
for (int i = 0; i String letter = LETTERS[i];
// 计算字体放置x坐标
int x = (int) (cellWidth / 2.0f - mPaint.measureText(letter) / 2.0f);
// 获取文本的高度
Rect rect = new Rect();// 矩形
mPaint.getTextBounds(letter, 0, letter.length(), rect);
int letterHeight = rect.height();
// 每个text单元格增加高度
int y = (int) (cellHeight / 2.0f + letterHeight / 2.0f + i * cellHeight);
// 根据按下的字母, 设置画笔颜色
mPaint.setColor(touchIndex == i ? Color.BLACK : Color.GRAY);
canvas.drawText(letter, x, y, mPaint);
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
int index = 0;
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
// 得到index值,总高度/每个单元格的高度
index = (int) (event.getY() / cellHeight);
if (index >= 0 && index // 判断是否同个一index,是就不再显示
if (touchIndex != index) {
if (mLetterIndexChangeListener != null) {
mLetterIndexChangeListener.onLetterIndexChange(LETTERS[index]);
}
// 记录当前index
touchIndex = index;
}
}
break;
case MotionEvent.ACTION_MOVE:
index = (int) (event.getY() / cellHeight);
if (index >= 0 && index if (touchIndex != index) {
if (mLetterIndexChangeListener != null) {
mLetterIndexChangeListener.onLetterIndexChange(LETTERS[index]);
}
touchIndex = index;
}
}
break;
case MotionEvent.ACTION_UP:
touchIndex = -1;
break;
}
invalidate();
return true;
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
// 获取单元格的宽
cellWidth = getMeasuredWidth();
int mHeight = getMeasuredHeight();
// 获取单元格的高
cellHeight = mHeight * 1.0f / LETTERS.length;
}
}
MainActivity:
public class MainActivity extends AppCompatActivity {
private ArrayList datas;
private TextView tv_center;
private Animation alpha_show;
private Animation alpha_die;
private boolean animatiOnState= true;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
alpha_show = AnimationUtils.loadAnimation(this, R.anim.alpha_show);
alpha_die = AnimationUtils.loadAnimation(this, R.anim.alpha_die);
datas = new ArrayList<>();
QuickIndexView qi_view = (QuickIndexView) findViewById(R.id.qi_view);
tv_center = (TextView) findViewById(R.id.tv_center);
final ListView lv_itme = (ListView) findViewById(R.id.lv_itme);
qi_view.setOnLetterIndexChangeListener(new QuickIndexView.OnLetterIndexChangeListener() {
@Override
public void onLetterIndexChange(String letter) {
showCenterIndex(letter);
for (int i = 0; i Person person = datas.get(i);
String index = person.getPinYin().charAt(0)+"";
if (TextUtils.equals(index,letter)){
lv_itme.setSelection(i);
break;
}
}
}
});
datas = fillAndSortData();
lv_itme.setAdapter(new MainAdapter(datas, getApplicationContext()));
}
private Handler mHandler = new Handler();
private void showCenterIndex(String letter) {
tv_center.setText(letter);
if (animationState){
tv_center.startAnimation(alpha_show);
animatiOnState= false;
}
tv_center.setVisibility(View.VISIBLE);
mHandler.removeCallbacksAndMessages(null);
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
animatiOnState= true;
tv_center.startAnimation(alpha_die);
tv_center.setVisibility(View.GONE);
}
},1000);
}
private ArrayList fillAndSortData() {
ArrayList PersOns= new ArrayList<>();
for (int i = 0; i String name = Cheeses.NAMES[i];
Persons.add(new Person(name));
}
Collections.sort(Persons);
return Persons;
}
}
Adapter:
public class MainAdapter extends BaseAdapter {
private ArrayList datas;
Context context;
public MainAdapter(ArrayList datas, Context context) {
this.datas = datas;
this.cOntext= context;
}
@Override
public int getCount() {
return datas.size();
}
@Override
public Object getItem(int position) {
return datas.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder mHolder = null;
if (cOnvertView== null) {
mHolder = new ViewHolder();
}else{
mHolder = (ViewHolder) convertView.getTag();
}
String str = null;
String index = datas.get(position).getPinYin().charAt(0) + "";
if (position == 0) {
str = index;
} else {
//获取上一个inedx判断时否相等
String preIndex = datas.get(position - 1).getPinYin().charAt(0) + "";
if (!TextUtils.equals(preIndex, index)) {
str = index;
}
}
// 根据str是否为空缺定是否显示
mHolder.lv_index.setVisibility(str == null?View.GONE: View.VISIBLE);
mHolder.lv_index.setText(index);
mHolder.lv_name.setText(datas.get(position).getName().trim());
return mHolder.getView();
}
class ViewHolder {
public TextView lv_index;
public TextView lv_name;
public View view;
public ViewHolder() {
view = View.inflate(context, R.layout.list_itme, null);
lv_index = (TextView) view.findViewById(R.id.lv_index);
lv_name = (TextView) view.findViewById(R.id.lv_name);
view.setTag(this);
}
public View getView() {
return view;
}
}
}
获取拼音:
public class PinYinHelper {
public static String getPinyin(String text) {
HanyuPinyinOutputFormat hFormat = new HanyuPinyinOutputFormat();
// 大写
hFormat.setCaseType(HanyuPinyinCaseType.UPPERCASE);
// 没有声调
hFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
char[] charArray = text.toCharArray();
StringBuilder sb = new StringBuilder();
for (int i = 0; i char c = charArray[i];
// 空格跳过
if (Character.isWhitespace(c)) {
continue;
}
if (c >= -127 && c <128) {
// 不是汉字
sb.append(c);
} else {
String pinYin = "";
try {
pinYin = PinyinHelper.toHanyuPinyinStringArray(c, hFormat)[0];
sb.append(pinYin);
} catch (BadHanyuPinyinOutputFormatCombination e) {
e.printStackTrace();
sb.append(pinYin);
}
}
}
return sb.toString();
}
}