版權聲明:本文爲博主原創文章,未經博主允許不得轉載。 https://blog.csdn.net/huangf321123/article/details/52870435
由於項目需要做一個仿通訊錄搜索聯繫人的功能,並且需要選中聯繫人,即推薦好友的功能。所以就想寫一遍blog來介紹它是怎麼實現,以及是怎麼用的。好的,接下來,讓我爲大家講解一下它是怎麼生出來的。
首先,給大家上一個功能示例圖。
以上四張圖片是通過本人截圖所得的,雖然不是很好看,但大概意思應該都能明白。大致有3個分類功能:一是輸入框搜索,二是側邊欄搜索,三是聯繫人的單選,全選以及反選功能。那下面,我們進行一一講解。
1. 獲取通訊錄聯繫人的信息:姓名、電話號碼。
## 注意哦,需要添加讀取權限 ##
<!-- 讀取聯繫人權限 -->
<uses-permission android:name="android.permission.READ_CONTACTS" />
```
## 具體獲取聯繫人的代碼如下 ##
```
/**得到手機通訊錄聯繫人信息**/
private void getPhoneContacts() {
ContentResolver resolver = getContentResolver();
// 獲取手機聯繫人
Cursor phoneCursor = resolver.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,PHONES_PROJECTION, null, null, null);
persons = new ArrayList<Person>();
if (phoneCursor != null) {
while (phoneCursor.moveToNext()) {
//得到手機號碼
String phoneNumber = phoneCursor.getString(PHONES_NUMBER_INDEX).toString().trim();
Log.e("xxx",phoneNumber);
//當手機號碼爲空的或者爲空字段 跳過當前循環
if (TextUtils.isEmpty(phoneNumber))
continue;
//得到聯繫人名稱
String contactName = phoneCursor.getString(PHONES_DISPLAY_NAME_INDEX);
Person p21 = new Person(contactName,phoneNumber);
persons.add(p21);
}
phoneCursor.close();
}
mHandler.sendEmptyMessage(0);
}
2. 根據輸入框輸入關鍵字搜索聯繫人。
##中文轉英文##
/**
* 中文轉英文
*
* @param src
* @return
*/
public static String getPingYin(String src) {
char[] t1 = null;
t1 = src.toCharArray();
String[] t2 = new String[t1.length];
HanyuPinyinOutputFormat t3 = new HanyuPinyinOutputFormat();
t3.setCaseType(HanyuPinyinCaseType.LOWERCASE);
t3.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
t3.setVCharType(HanyuPinyinVCharType.WITH_V);
String t4 = "";
int t0 = t1.length;
try {
for (int i = 0; i < t0; i++) {
// 判斷是否爲漢字字符
if (java.lang.Character.toString(t1[i]).matches(
"[\\u4E00-\\u9FA5]+")) {
t2 = PinyinHelper.toHanyuPinyinStringArray(t1[i], t3);
t4 += t2[0];
} else {
t4 += java.lang.Character.toString(t1[i]);
}
}
return t4;
} catch (BadHanyuPinyinOutputFormatCombination e1) {
e1.printStackTrace();
}
return t4;
}
## 中文首字母縮寫 ##
/**
* 得到中文首字母縮寫
*
* @param str
* @return
*/
public static String getPinYinHeadChar(String str) {
String convert = "";
for (int j = 0; j < str.length(); j++) {
char word = str.charAt(j);
String[] pinyinArray = PinyinHelper.toHanyuPinyinStringArray(word);
if (pinyinArray != null) {
convert += pinyinArray[0].charAt(0);
} else {
convert += word;
}
}
return convert.toUpperCase();
}
## 根據字母搜索 ##
其主要原理是通過比對輸入的關鍵字與程序所存的通訊錄數組中的拼音(中文轉拼音)。現在這裏做的只要是包含該關鍵字的拼音,都搜索出來,並沒有根據通訊錄中姓名的首字母進行搜索,當然,如果要實現的話,也是可以的。
/**
* 根據字母拼音搜索
* @param letter
*/
private void searchbyLetter(final String letter) {
new Thread(new Runnable() {
@Override
public void run() {
getData(letter);
}
}).start();
}
private void getData(String ll) {
letters.clear();
for(Person p:persons){
if(p.getPinYinName().contains(StringHelper.CapitalToSmallLetter(ll))){
letters.add(p);
}
}
Message msg = new Message();
msg.what = 3;
mHandler.sendMessage(msg);
}
## 根據中文搜索 ##
其主要原理大致與上面一致。
/**
* 根據中文搜索
* @param search
*/
private void searchbyChinese(final String search) {
new Thread(new Runnable() {
@Override
public void run() {
getChineseData(search);
}
}).start();
}
private void getChineseData(String search) {
chineses.clear();
for(Person p:persons){
Log.e("xxx",p.getName()+">>>"+search);
if(p.getName().contains(search)){
chineses.add(p);
}
}
Message msg = new Message();
msg.what = 4;
mHandler.sendMessage(msg);
}
##區分輸入的關鍵字是中文還是英文 ##
/**
* 判斷中文或者是英文
* @param value
* @return
*/
public static boolean isLetter(String value){
// Pattern p = Pattern.compile("[0-9]*");
// Matcher m = p.matcher(value);
// if(m.matches() ){
// Toast.makeText(Main.this,"輸入的是數字", Toast.LENGTH_SHORT).show();
// }
// p=Pattern.compile("[a-zA-Z]");
// m=p.matcher(value);
// if(m.matches()){
// Toast.makeText(Main.this,"輸入的是字母", Toast.LENGTH_SHORT).show();
// }
String flag = "";
int len = value.length();
Pattern p=Pattern.compile("[\u4e00-\u9fa5]");
for(int i = 0;i < len ;i++){
String s = value.substring(i,i+1);
Log.e("xxx",s);
Matcher m=p.matcher(s);
if(m.matches()){
flag += "tu"+",";
}else{
flag += "fa"+",";
}
}
Log.e("xx",flag);
if(flag != null && flag.contains("fa")){
return false;
}
return true;
}
3. 側邊欄滾動搜索。
## 繪製索引列表 ##
private String[] indexStr = { "#", "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" };
@Override
public void onWindowFocusChanged(boolean hasFocus) {
// 在oncreate裏面執行下面的代碼沒反應,因爲oncreate裏面得到的getHeight=0
if (!flag) {// 這裏爲什麼要設置個flag進行標記,我這裏不先告訴你們,請讀者研究,因爲這對你們以後的開發有好處
height = layoutIndex.getMeasuredHeight() / indexStr.length;
getIndexView();
flag = true;
}
}
/**
* 繪製索引列表
*/
public void getIndexView() {
LinearLayout.LayoutParams params = new LayoutParams(
LayoutParams.WRAP_CONTENT, height);
for (int i = 0; i < indexStr.length; i++) {
final TextView tv = new TextView(this);
tv.setLayoutParams(params);
tv.setText(indexStr[i]);
tv.setPadding(10, 0, 10, 0);
layoutIndex.addView(tv);
layoutIndex.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event)
{
float y = event.getY();
int index = (int) (y / height);
if (index > -1 && index < indexStr.length) {// 防止越界
String key = indexStr[index];
if (selector.containsKey(key)) {
int pos = selector.get(key);
if (listView.getHeaderViewsCount() > 0) {// 防止ListView有標題欄,本例中沒有。
listView.setSelectionFromTop(
pos + listView.getHeaderViewsCount(), 0);
} else {
listView.setSelectionFromTop(pos, 0);// 滑動到第一項
}
tv_show.setVisibility(View.VISIBLE);
tv_show.setText(indexStr[index]);
}
}
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
layoutIndex.setBackgroundColor(Color
.parseColor("#f2f2f2"));
break;
case MotionEvent.ACTION_MOVE:
break;
case MotionEvent.ACTION_UP:
layoutIndex.setBackgroundColor(Color
.parseColor("#00ffffff"));
tv_show.setVisibility(View.GONE);
break;
}
return true;
}
});
}
}
4. 聯繫人的單選,全選以及反選功能。
##適配器中配置接口##
interface onCheckChangeListen{
void showBottom();
}
public void setOnCheckChange(onCheckChangeListen listen){
this.mListen = listen;
}
## 在主程序中進行調用 ##
//監聽列表中checkbox的狀態變化
adapter.setOnCheckChange(new ListViewAdapter.onCheckChangeListen() {
@Override
public void showBottom() {
String flag = "";
count = 0;
for(Person p:newPersons){
flag += p.isChecked()+",";
}
Log.e("xxx",flag);
String[] value = flag.split(",");
for(int i=0;i<value.length;i++){
if(value[i].equals("true")){
count += 1 ;
}
}
if(count == 0){
mBottomLayout.setVisibility(View.GONE);
}else if(count > 0){
mBottomLayout.setVisibility(View.VISIBLE);
mPersonCount.setText("選中"+count+"個聯繫人");
}
}
});
## 全選與反選 ##
//全選or反選
mCheck.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if(isChecked){
for(Person p:newPersons){
p.setChecked(isChecked);
}
mCheck.setChecked(true);
adapter.notifyDataSetChanged();
}else{
for(Person p:newPersons){
p.setChecked(false);
}
mCheck.setChecked(false);
adapter.notifyDataSetChanged();
mBottomLayout.setVisibility(View.GONE);
}
}
});
以上就是構成該項目的主要代碼。其完整的demo在下面。