通讯录的搜索功能,关键字变色,支持全拼,首字母,不区分大小写等效果,用到了 'com.belerweb:pinyin4j:2.5.1'
效果图
主要涉及到如何确定一个汉字占到几个字母的方法
依赖
compile 'com.android.support:appcompat-v7:25.3.0'
compile 'com.belerweb:pinyin4j:2.5.1'
compile 'com.android.support:design:25.3.0'
compile 'com.google.code.gson:gson:2.3.1'
compile 'com.github.bumptech.glide:glide:3.7.0'
布局代码
Activity代码
public class MainActivity extends AppCompatActivity implements SearchView.OnQueryTextListener {
private SearchView search_view;
private RecyclerView recycler_view;
private HashSet infos;
private String search;
private MyAdapter myAdapter;
private List persons = Info.getInfo();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
initData();
initAction();
}
public void initView() {
search_view = (SearchView) findViewById(R.id.search_view);
//修改SearchView字体
int id = search_view.getContext().getResources().getIdentifier("android:id/search_src_text", null, null);
TextView textView = (TextView) search_view.findViewById(id);
textView.setTextColor(UiUtil.getColor(MainActivity.this, R.color.blue_style));//字体颜色
textView.setTextSize(14);//字体、提示字体大小
textView.setHintTextColor(UiUtil.getColor(MainActivity.this, R.color.font_color));//提示字体颜色**
//反射修改SearchView背景
try {
Class> argClass = search_view.getClass();
Field ownField = argClass.getDeclaredField("mSearchPlate");
ownField.setAccessible(true);
View mView = (View) ownField.get(search_view);
mView.setBackgroundColor(Color.WHITE);
} catch (Exception e) {
e.printStackTrace();
}
recycler_view = (RecyclerView) findViewById(R.id.recycler_view);
recycler_view.setLayoutManager(new LinearLayoutManager(MainActivity.this));
}
public void initData() {
infos = new HashSet();
myAdapter = new MyAdapter();
recycler_view.setAdapter(myAdapter);
}
public void initAction() {
search_view.setOnQueryTextListener(this);
}
@Override
public boolean onQueryTextSubmit(String query) {
return true;
}
@Override
public boolean onQueryTextChange(String newText) {
infos.clear();
search = newText;
if (TextUtils.isEmpty(newText)) {
myAdapter.notifyDataChanged(persons);
} else {
int size = persons.size();
for (int i = 0; i < size; i++) {
Person bean = persons.get(i);
String nikeName = bean.getNikeName();
if (UiUtil.contain(nikeName, newText)) {
bean.type = 2;//姓名
infos.add(bean);
continue;
}
if (bean.getPhoneNum().contains(newText)) {
bean.type = 3;//手机
infos.add(bean);
continue;
}
String firstSpell = UiUtil.getFirstSpell(nikeName);
if (UiUtil.contain(firstSpell, newText)) {
bean.type = 4;//缩写
infos.add(bean);
continue;
}
String pingYin = UiUtil.getPingYin(nikeName);
if (UiUtil.contain(pingYin, newText)) {
bean.type = 5;//全拼
infos.add(bean);
continue;
}
}
myAdapter.notifyDataChanged(infos);
}
return false;
}
public void setColor(TextView view, String text, int type) {
int index;
ForegroundColorSpan span = new ForegroundColorSpan(UiUtil.getColor(MainActivity.this, R.color.blue_style));//要显示的颜色
SpannableStringBuilder builder = new SpannableStringBuilder(text);
switch (type) {
case 2://姓名
index = text.toLowerCase().indexOf(search.toLowerCase());
if (index != -1) {
builder.setSpan(span, index, index + search.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
view.setText(builder);
} else {
view.setText(builder);
}
break;
case 3://电话
index = text.indexOf(search);
if (index != -1) {
builder.setSpan(span, index, index + search.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
view.setText(builder);
} else {
view.setText(builder);
}
break;
case 4://缩写
String lowerCase = search.toLowerCase();//全部小写
String firstSpell = UiUtil.getFirstSpell(text);
index = firstSpell.indexOf(lowerCase);
if (index != -1) {
builder.setSpan(span, index, index + search.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
view.setText(builder);
} else {
view.setText(text);
}
break;
case 5://全拼
String lowerCase1 = search.toLowerCase();//全部小写
int count = text.length();//文字个数
int start = -1;//开始位置
int end = -1;//结束位置
for (int i = 1; i < count + 1; i++) {//每次截取的字符个数
for (int j = 0; j < count; j++) {//开始位置
String sub;
if (j + i <= count) {//当截取的个数小于字符串长度时,直接截取
sub = text.substring(j, j + i);
} else {//否则截取后面的全部内容
sub = text.substring(j);
}
String pinYin = UiUtil.getPingYin(sub);//获取截取的拼音
if (pinYin.contains(lowerCase1)) {//如果截取的字符串能够匹配到
start = j;//记录开始位置
end = j + i < count ? j + i : count;//结束位置
i = count + 1;//跳出外层循环
break;//跳出内层循环
}
}
}
//设置变色范围
if (start != -1 && end != -1) {
builder.setSpan(span, start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
view.setText(builder);
} else {
view.setText(text);
}
break;
}
}
class MyAdapter extends RecyclerView.Adapter {
private List persons = new ArrayList();
public MyAdapter() {
List info = Info.getInfo();
persons.addAll(info);
}
@Override
public MyAdapter.MyHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View inflate = View.inflate(parent.getContext(), R.layout.layout_item, null);
return new MyAdapter.MyHolder(inflate);
}
@Override
public void onBindViewHolder(MyAdapter.MyHolder holder, int position) {
Person person = persons.get(position);
String nikeName = person.getNikeName();
String phoneNum = person.getPhoneNum();
Glide.with(MainActivity.this).load(person.getPhoto()).into(holder.iv_photo);
switch (person.type) {
case 2://姓名
setColor(holder.tv_name, nikeName, 2);
holder.tv_phone.setText(phoneNum);
break;
case 3://手机
holder.tv_name.setText(nikeName);
setColor(holder.tv_phone, phoneNum, 3);
break;
case 4://缩写
setColor(holder.tv_name, nikeName, 4);
holder.tv_phone.setText(phoneNum);
break;
case 5://全拼
setColor(holder.tv_name, nikeName, 5);
holder.tv_phone.setText(phoneNum);
break;
default:
holder.tv_name.setText(nikeName);
holder.tv_phone.setText(phoneNum);
break;
}
}
@Override
public int getItemCount() {
return persons.size();
}
public void notifyDataChanged(Collection infos) {
this.persons.clear();
this.persons.addAll(infos);
this.notifyDataSetChanged();
}
class MyHolder extends RecyclerView.ViewHolder {
ImageView iv_photo;
TextView tv_name;
TextView tv_phone;
public MyHolder(View itemView) {
super(itemView);
iv_photo = (ImageView) itemView.findViewById(R.id.iv_photo);
tv_name = (TextView) itemView.findViewById(R.id.tv_name);
tv_phone = (TextView) itemView.findViewById(R.id.tv_phone);
}
}
}
}
工具类
public class UiUtil {
/**
* 获取屏幕密度
* @param context
* @return
*/
public static float getCount(Context context) {
return context.getResources().getDisplayMetrics().density;
}
/**
* px-->dp
* @param context
* @param dp
* @return
*/
public static int dp2px(Context context ,int dp) {
return (int) (dp * getCount(context));
}
/**
* px-->dp
* @param context
* @param px
* @return
*/
public static int px2dp(Context context ,int px) {
return (int) (px / getCount(context));
}
/**
* 获取图片
* @param context
* @param id
* @return
*/
public static Drawable getDrawable(Context context ,int id) {
return context.getResources().getDrawable(id);
}
/**
* 获取颜色集合
* @param context
* @param id
* @return
*/
public static ColorStateList getColorStateList(Context context ,int id) {
return context.getResources().getColorStateList(id);
}
/**
* 获取颜色
* @param context
* @param id
* @return
*/
public static int getColor(Context context ,int id) {
return context.getResources().getColor(id);
}
/**
* 获取dp
* @param context
* @param id
* @return
*/
public static float getdp(Context context ,int id) {
return context.getResources().getDimension(id);
}
/**
* 将字符串中的中文转化为拼音,其他字符不变
*
* @param chinese
* @return
*/
public static String getPingYin(String chinese) {
HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat();
format.setCaseType(HanyuPinyinCaseType.LOWERCASE);
format.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
format.setVCharType(HanyuPinyinVCharType.WITH_V);
char[] input = chinese.trim().toCharArray();
String output = "";
try {
for (char curchar : input) {
if (Character.toString(curchar).matches(
"[\\u4E00-\\u9FA5]+")) {
String[] temp = PinyinHelper.toHanyuPinyinStringArray(
curchar, format);
if (temp != null&&temp.length>0){
output += temp[0];
}else {
output += Character.toString(curchar);
}
} else {
output += Character.toString(curchar);
}
}
} catch (BadHanyuPinyinOutputFormatCombination e) {
e.printStackTrace();
}
return output.toLowerCase();
}
/**
* 汉字转换为汉语拼音首字母,英文字符不变
*
* @param chinese 汉字
* @return 拼音
*/
public static String getFirstSpell(String chinese) {
if (chinese.length() > 0) {
StringBuffer pybf = new StringBuffer();
char[] arr = chinese.toCharArray();
HanyuPinyinOutputFormat defaultFormat = new HanyuPinyinOutputFormat();
defaultFormat.setCaseType(HanyuPinyinCaseType.LOWERCASE);
defaultFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
for (char curchar : arr) {
if (curchar > 128) {
try {
String[] temp = PinyinHelper.toHanyuPinyinStringArray(curchar, defaultFormat);
if (temp != null&&temp.length>0&&temp[0].length()>0) {
pybf.append(temp[0].charAt(0));
}
} catch (BadHanyuPinyinOutputFormatCombination e) {
e.printStackTrace();
}
} else {
pybf.append(curchar);
}
}
return pybf.toString().trim().toLowerCase();
}
return "";
}
/**
* 重写contain方法
* @param input
* @param chinese
* @return
*/
public static boolean contain(String input, String chinese) {
boolean result;
try {
Pattern p = Pattern.compile(chinese.toLowerCase(), Pattern.LITERAL);
Matcher m = p.matcher(input.toLowerCase());
result = m.find();
} catch (Exception e) {
return false;
}
return result;
}
}
实体类
public class Person {
public Person(String nikeName, String phoneNum, int photo) {
this.nikeName = nikeName;
this.phoneNum = phoneNum;
this.photo = photo;
}
/**
* nikeName : 无用)
* phoneNum : 12115234568
* photo : 1
*/
private String nikeName;
private String phoneNum;
private int photo;
public int type;
public String getNikeName() {
return nikeName;
}
public void setNikeName(String nikeName) {
this.nikeName = nikeName;
}
public String getPhoneNum() {
return phoneNum;
}
public void setPhoneNum(String phoneNum) {
this.phoneNum = phoneNum;
}
public int getPhoto() {
return photo;
}
public void setPhoto(int photo) {
this.photo = photo;
}
}
数据
public class Info {
public static final int[] PHOTOS = {R.drawable.a0, R.drawable.a1, R.drawable.a2, R.drawable.a3, R.drawable.a4,
R.drawable.a5, R.drawable.a6, R.drawable.a7, R.drawable.a8, R.drawable.a9,R.drawable.a10, R.drawable.a11,
R.drawable.a12, R.drawable.a13, R.drawable.a14, R.drawable.a15, R.drawable.a16, R.drawable.a17, R.drawable.a18,
R.drawable.a19, R.drawable.a20, R.drawable.a21, R.drawable.a22, R.drawable.a23, R.drawable.a24, R.drawable.a25,
R.drawable.a26, R.drawable.a27, R.drawable.a28, R.drawable.a29};
public static final String[] NAMES = new String[]{"宋江0", "卢俊义1", "吴用2",
"公孙胜3", "关胜4", "林冲5", "秦明6", "呼延灼7", "花荣8", "柴进9", "李应10", "朱仝11", "鲁智深12",
"武松13", "董平14", "张清15", "杨志16!", "徐宁17!", "索超18@", "戴宗19dz", "刘唐20LT", "李逵21)", "史进22)", "穆弘23.",
"雷横24,", "李俊25、", "阮小二26,", "张横27。", "阮小五28】", " 张顺29]"};
public static final String[] PHONES = {"13612345678", "12115234568", "12365548547", "15647892435", "13649237325", "18623458965", "18654235987",
"16578954352", "15637646854", "13254685723", "15764235684", "14352645875", "15478652354", "15647254556", "12586875434",
"12543698754", "16753245698", "15423657895", "13548567895", "15675482431", "13458645297", "15243652141", "12436851254",
"13245426789", "13254255235", "14578523698", "12300000007", "12423564785", "14253652362", "13542621421"};
public static List getInfo() {
ArrayList persons = new ArrayList<>();
for (int i = 0; i < NAMES.length; i++) {
persons.add(new Person(NAMES[i], PHONES[i], PHOTOS[i]));
}
return persons;
}
}