android-仿手机通讯录(支持索引导航和搜索功能)
程序员文章站
2024-02-27 21:11:15
...
最近公司需要实现类似于手机通讯录的功能,并支持搜索功能,今天便简单写了一下。基本功能已经实现。我们先看一下效果。联系QQ878586063。以下晒出来的代码,是全部代码。代码不多,大家感受一下。
首页我们看下索引导航View,特别简单一看就懂,这个类已经用模拟器试过除了手表所有的机型,都是可以的。
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
for (int i = 0; i < codes.length; i++) {
if (codes[i].equals("#")) {
canvas.drawBitmap(mBitmap, 8 * displayMetrics.density, lineHeight * (i + 1), paint);
} else {
canvas.drawText(codes[i], 10 * displayMetrics.density, 7 * displayMetrics.density + lineHeight * (i + 1), paint);
}
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
setMeasuredDimension((int) (viewHeight * displayMetrics.density), (int) (lineHeight * codes.length + 13 * displayMetrics.density));
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
setAlpha(0.5f);
setBackgroundColor(Color.GRAY);
float y = event.getY();
int v = (int) ((y - 6.5 * displayMetrics.density) / lineHeight);
if (v >= 0 && v <= codes.length - 1) {
if (moveEvent != null)
moveEvent.move(codes[v]);
}
break;
case MotionEvent.ACTION_MOVE:
y = event.getY();
v = (int) ((y - 6.5 * displayMetrics.density) / lineHeight);
if (v >= 0 && v <= codes.length - 1) {
if (moveEvent != null)
moveEvent.move(codes[v]);
}
break;
case MotionEvent.ACTION_UP:
setBackgroundColor(Color.WHITE);
setAlpha(1f);
break;
}
return super.onTouchEvent(event);
}
接下来我们看下怎么处理的:
//数据类
*
* Created by yang pengtao on 2017/9/19.
*/
public class SelectCountryCodeBean implements Serializable {
private List<CodesBean> codes;
public List<CodesBean> getCodes() {
return codes;
}
public void setCodes(List<CodesBean> codes) {
this.codes = codes;
}
public static class CodesBean {
/**
* cname : 福克兰群岛(马尔维纳斯)
* ename : Falkland Islands (Islas Malvinas)
* code : +500
*/
private String cname;
private String ename;
private String code;
private String first_letter;
private int type = 1;
public String getCname() {
return cname;
}
public void setCname(String cname) {
this.cname = cname;
}
public String getEname() {
return ename;
}
public void setEname(String ename) {
this.ename = ename;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getFirst_letter() {
return first_letter;
}
public void setFirst_letter(String first_letter) {
this.first_letter = first_letter;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
}
}
我们得到数据后先要处理一下,用pinyin4j.jar得到汉字拼音首字母,还要得到字母显示在列表中的下标,用于我们列表滚动。如果大家需要pinyin4j.jar。戳这里。
/**
* 重置数据成自己想要的数据
*
* @param data 要被重置的数据
*/
private void resetData(List<SelectCountryCodeBean.CodesBean> data) {
for (int i = 0; i < data.size(); i++) {
String[] pinyinArray = PinyinHelper.toHanyuPinyinStringArray(data.get(i).getCname().charAt(0));
if (pinyinArray != null) {
String s = pinyinArray[0].substring(0, 1).toUpperCase();
data.get(i).setFirst_letter(s);
if (!positions.containsKey(s)) {
positions.put(s, i);
}
}
}
}
有了数据我们就可以把数据显示到我们的列表上了,我用到了我写的上一篇封装的适配器,用起来非常方便,不用编写adapter和view holder,看下面代码,感受一下。希望大家赶快用起来吧。想学习的可以直接看暴力封装Adapter。
/**
* 设置adapter
*/
private void setAdapter() {
listview.setAdapter(new BaseAdapter<SelectCountryCodeBean.CodesBean>(R.layout.layout_select_country_code, codes) {
@Override
public void onBindViewHolder(BaseViewHolder holder, List<SelectCountryCodeBean.CodesBean> data, int position) {
if (position != 0 && data.get(position).getFirst_letter().equals(data.get(position - 1).getFirst_letter())) {
holder.getView(R.id.code).setVisibility(View.GONE);
} else {
holder.getView(R.id.code).setVisibility(View.VISIBLE);
}
holder.setText(R.id.code, data.get(position).getFirst_letter());
holder.setText(R.id.country, data.get(position).getCname() + "(" + data.get(position).getEname() + ")").setText(R.id.country_code, data.get(position).getCode());
}
});
}
实现索引导航的代码也只不过仅仅几行,来感受虾:
/**
* 索引导航
*/
private void indexNavigae() {
((ZoomImageView) findViewById(R.id.leftView)).setMoveEvent(new ZoomImageView.MoveEvent() {
@Override
public void move(String code) {
if (positions.get(code) != null) {
linearLayoutManager.scrollToPositionWithOffset(positions.get(code), 0);
}
}
});
}
最后就只有我们的搜索功能,闲话不多说,直接感受:
/**
* 搜索数据
*
* @param s 搜索字符
*/
public void searchResetData(String s) {
serachData.clear();
//如果为null,直接使用全部数据
if (s.equals("")) {
serachData.addAll(codes);
} else {
//否则,匹配相应的数据
for (int i = 0; i < codes.size(); i++) {
if (codes.get(i).getCname().indexOf(s) >= 0 || codes.get(i).getEname().indexOf(s) >= 0) {//这里可拓展自己想要的,甚至可以拆分搜索汉字来匹配
serachData.add(codes.get(i));
}
}
}
//绑定索引
positions.clear();
resetData(serachData);
//刷新数据
((BaseAdapter<SelectCountryCodeBean.CodesBean>) listview.getAdapter()).setmData(serachData);
}
最后有一点非常重要:给IndexNavigateView加一个click事件,否则触摸事件回合recyclerView冲突。
到这就结束了,是不是特别简单,欢迎评论反馈。大家支持一下。
下一篇: web通讯录之搜索功能