仿小米联系人
实现分析:
1.自定义右侧的字母栏,
2.展示数据的listview或者RecycleView
3.圆形TextView
4.集合排序(Comparator)的类
5.中文转拼音
实现代码:
1、自定义右侧的字母栏:
根据控件高度计算字体的大小,字母所占的高度通过滑动改变圆形标记,以及listview的显示;
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int heigth = getHeight();
int width = getWidth();
//每一个字母的高度
letter_heigth = heigth / letter.length;
//圆形标记画笔设置
round_paint.setColor(Color.parseColor("#ffff00"));
round_paint.setAntiAlias(true);
//计算Size
size = (int) (letter_heigth / 1.5);
canvas.drawCircle(width / 2, round_Y - (letter_heigth / 2), size / 2 + 7, round_paint);
for (int i = 0; i < letter.length; i++) {
paint.setColor(Color.parseColor("#1f2b65"));
paint.setAntiAlias(true);
paint.setTextSize(size);
if (i == select) {
//如果选中,改变颜色,size
// paint.setColor(Color.parseColor("#fc1206"));
paint.setTextSize(size + 10);
}
//文本居中
float letter_X = (width - paint.measureText(letter[0])) / 2;
float letter_Y = letter_heigth * i + letter_heigth - (size / 2);
canvas.drawText(letter[i], letter_X, letter_Y, paint);
paint.reset();
}
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
int action = event.getAction();
round_Y = (int) event.getY();
//计算下标
select = round_Y / letter_heigth;
//为了美观,不然圆形标记滑出屏幕
if (round_Y > getHeight() - letter_heigth) {
round_Y = getHeight() - letter_heigth;
} else if (round_Y < letter_heigth) {
round_Y = letter_heigth;
}
switch (action) {
case MotionEvent.ACTION_UP:
getBackground().setAlpha(0);
if (select < 0) {
select = 0;
} else if (select >= letter.length) {
select = letter.length - 1;
}
round_Y = letter_heigth * select + letter_heigth;
if (listener != null) {
listener.onLetterListener(letter[select], -1);
}
select = -1;
invalidate();
break;
default:
setBackgroundColor(Color.parseColor("#c0bebe"));
getBackground().setAlpha(100);
if (select >= 0 && select < letter.length) {
if (listener != null) {
listener.onLetterListener(letter[select], select);
}
invalidate();
}
break;
}
return true;
}
2、展示数据的listview或者RecycleView:
实现方式有2中,这里介绍单布局实现:
通过判断是否是第一次显示,来确定是否隐藏字母栏
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder = null;
ListSort.Letter letter = list.get(position);
if (convertView == null) {
convertView = LayoutInflater.from(context).inflate(R.layout.item, null);
viewHolder = new ViewHolder();
viewHolder.letter_tv = (TextView) convertView.findViewById(R.id.item_letter);
viewHolder.name_tv = (TextView) convertView.findViewById(R.id.item_name);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
//判断是否是第一次出现,不是的话就隐藏字母栏
if (getFristVisibility(letter.frist_Letter) == position) {
viewHolder.letter_tv.setVisibility(View.VISIBLE);
viewHolder.letter_tv.setText(letter.frist_Letter);
} else {
viewHolder.letter_tv.setVisibility(View.GONE);
}
viewHolder.name_tv.setText(letter.name);
return convertView;
}
//得到第一次显示字母下标
public int getFristVisibility(String string) {
for (int i = 0; i < list.size(); i++) {
String str = list.get(i).frist_Letter;
if (string.equals(str)) {
return i;
}
}
return -1;
}
3、圆形TextView:
2种方式:shape标签实现参考圆形圆角Dialog的实现
这里介绍另一种简单粗暴的方式:
protected void onDraw(Canvas canvas) {
if (getBackground() != null) {
getBackground().setAlpha(0);
}
radius = getWidth() >= getHeight() ? getHeight() : getWidth();
paint.setColor(Color.parseColor("#c0bebe"));
paint.setAntiAlias(true);
canvas.drawCircle(radius / 2, radius / 2, radius / 2, paint);
super.onDraw(canvas);
}
4、集合排序(Comparator)的类
通过实现Comparator来完成:
/*
集合排序
*/
public class ListSort implements Comparator<ListSort.Letter> {
@Override
public int compare(Letter lhs, Letter rhs) {
if (lhs.frist_Letter.equals("@") || rhs.frist_Letter.equals("#")) {
return -1;
} else if (lhs.frist_Letter.equals("#") || rhs.frist_Letter.equals("@")) {
return 1;
} else {
return lhs.frist_Letter.compareTo(rhs.frist_Letter);
}
}
public static class Letter {
String name;
String frist_Letter;
}
}
5、中文转拼音:代码太长不贴了
链接地址:使用Java将中文转化为拼音