android 获取手机通讯录联系人,模拟通讯录显示
2016-04-14 17:05
651 查看
资源:点击打开链接
汉字转换为拼音,使用pinyin4j-2.5.0.jar库;之前使用的CharacterParser工具库是有bug的,例如“斐”是解析不出来的;
搜索框 ClearEditText
右侧字母侧边框 sideBar
联系人没有首字母特殊处理 PinyinComparator
联系人对象 SortModel
数据显示格式定义类 SortAdapter
主页activity布局文件
数据显示item 布局文件
活动窗口:
AndroidManifest.xml文件,说明一下,获取手机通讯录,必须添加通讯录访问权限;即
运行效果图:
android 获取手机通讯录联系人,模拟通讯录显示
最近做项目,恰好有这样的需求;在网上搜搜,找到了许多相关的文章,但是多多少少有一些出入。现在整理一下,做个总结;有疑问可以@我!主要是获取手机通讯录,模拟手机通讯录的搜索、字母排序显示;
思路:
获取手机通讯录信息,对联系人名称进行处理,获取拼音、大写字母
详情可以参考:http://blog.csdn.net/csh159/article/details/8955029/
直接上代码
</pre><pre name="code" class="java"><pre name="code" class="java">package com.example.sortlistview; import java.util.ArrayList; import java.util.Collections; import java.util.List; import android.app.Activity; import android.content.ContentResolver; import android.database.Cursor; import android.os.Bundle; import android.provider.ContactsContract.CommonDataKinds.Phone; import android.provider.ContactsContract.Contacts.Photo; import android.text.Editable; import android.text.TextUtils; import android.text.TextWatcher; import android.view.View; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.ListView; import android.widget.TextView; import android.widget.Toast; import com.example.sortlistview.SideBar.OnTouchingLetterChangedListener; public class MainActivity extends Activity { private ListView sortListView; private SideBar sideBar; private TextView dialog; private SortAdapter adapter; private ClearEditText mClearEditText; /** * 汉字转换成拼音的类 */ private CharacterParser characterParser; private List<SortModel> SourceDateList; /** * 根据拼音来排列ListView里面的数据类 */ private PinyinComparator pinyinComparator; /** 联系人显示名称 **/ private static final int PHONES_DISPLAY_NAME_INDEX = 0; /** 电话号码 **/ private static final int PHONES_NUMBER_INDEX = 1; /** 头像ID **/ // private static final int PHONES_PHOTO_ID_INDEX = 2; /** 联系人的ID **/ // private static final int PHONES_CONTACT_ID_INDEX = 3; /** 库 phone表字段 **/ private static final String[] PHONES_PROJECTION = new String[] { Phone.DISPLAY_NAME, Phone.NUMBER, Photo.PHOTO_ID, Phone.CONTACT_ID }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initViews(); } private void initViews() { //实例化汉字转拼音类 characterParser = CharacterParser.getInstance(); pinyinComparator = new PinyinComparator(); sideBar = (SideBar) findViewById(R.id.sidrbar); dialog = (TextView) findViewById(R.id.dialog); sideBar.setTextView(dialog); //设置右侧触摸监听 sideBar.setOnTouchingLetterChangedListener(new OnTouchingLetterChangedListener() { @Override public void onTouchingLetterChanged(String s) { //该字母首次出现的位置 int position = adapter.getPositionForSection(s.charAt(0)); if(position != -1){ sortListView.setSelection(position); } } }); sortListView = (ListView) findViewById(R.id.country_lvcountry); sortListView.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { //这里要利用adapter.getItem(position)来获取当前position所对应的对象 Toast.makeText(getApplication(), ((SortModel)adapter.getItem(position)).getName(), Toast.LENGTH_SHORT).show(); } }); SourceDateList = loadPhoneContactData(); // 根据a-z进行排序源数据 Collections.sort(SourceDateList, pinyinComparator); adapter = new SortAdapter(this, SourceDateList); sortListView.setAdapter(adapter); mClearEditText = (ClearEditText) findViewById(R.id.filter_edit); //根据输入框输入值的改变来过滤搜索 mClearEditText.addTextChangedListener(new TextWatcher() { @Override public void onTextChanged(CharSequence s, int start, int before, int count) { //当输入框里面的值为空,更新为原来的列表,否则为过滤数据列表 filterData(s.toString()); } @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void afterTextChanged(Editable s) { } }); } /** * 加载手机联系人 */ private List<SortModel> loadPhoneContactData() { List<SortModel> mSortList = new ArrayList<SortModel>(); ContentResolver resolver = this.getContentResolver(); Cursor phoneCursor = resolver.query(Phone.CONTENT_URI, PHONES_PROJECTION, null, null, null); SortModel sort = null; String phoneNumber = ""; String phoneName = ""; // Long photoID = 0l; if (phoneCursor != null) { while (phoneCursor.moveToNext()) { // get phone number phoneNumber = phoneCursor.getString(PHONES_NUMBER_INDEX) .replace(" ", ""); if (phoneNumber==null||phoneNumber=="") continue; phoneName = phoneCursor.getString(PHONES_DISPLAY_NAME_INDEX); sort = new SortModel(); sort.setMobile(phoneNumber); sort.setName(phoneName); // 汉字转换成拼音 String pinyin = characterParser.getSelling(phoneName); String sortString = pinyin.substring(0, 1).toUpperCase(); sort.setSortLetters(sortString); // 正则表达式,判断首字母是否是英文字母 if (sortString.matches("[A-Z]")) { sort.setSortLetters(sortString.toUpperCase()); } else { sort.setSortLetters("#"); } mSortList.add(sort); } phoneCursor.close(); } return mSortList; } /** * 根据输入框中的值来过滤数据并更新ListView * @param filterStr */ private void filterData(String filterStr){ List<SortModel> filterDateList = new ArrayList<SortModel>(); if(TextUtils.isEmpty(filterStr)){ filterDateList = SourceDateList; }else{ filterDateList.clear(); for(SortModel sortModel : SourceDateList){ String name = sortModel.getName(); if(name.indexOf(filterStr.toString()) != -1 || characterParser.getSelling(name).startsWith(filterStr.toString())){ filterDateList.add(sortModel); } } } // 根据a-z进行排序 Collections.sort(filterDateList, pinyinComparator); adapter.updateListView(filterDateList); } }
汉字转换为拼音,使用pinyin4j-2.5.0.jar库;之前使用的CharacterParser工具库是有bug的,例如“斐”是解析不出来的;
package com.example.sortlistview; import net.sourceforge.pinyin4j.PinyinHelper; import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType; import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat; import net.sourceforge.pinyin4j.format.HanyuPinyinToneType; import net.sourceforge.pinyin4j.format.HanyuPinyinVCharType; import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination; public class ChineseToEnglish { // 将汉字转换为全拼 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]); } // System.out.println(t4); return t4; } catch (BadHanyuPinyinOutputFormatCombination e1) { e1.printStackTrace(); } return t4; } // 返回中文的首字母 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; } // 将字符串转移为ASCII码 public static String getCnASCII(String cnStr) { StringBuffer strBuf = new StringBuffer(); byte[] bGBK = cnStr.getBytes(); for (int i = 0; i < bGBK.length; i++) { strBuf.append(Integer.toHexString(bGBK[i] & 0xff)); } return strBuf.toString(); } }
搜索框 ClearEditText
package com.example.sortlistview; import android.content.Context; import android.graphics.drawable.Drawable; import android.text.Editable; import android.text.TextWatcher; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; import android.view.View.OnFocusChangeListener; import android.view.animation.Animation; import android.view.animation.CycleInterpolator; import android.view.animation.TranslateAnimation; import android.widget.EditText; public class ClearEditText extends EditText implements OnFocusChangeListener, TextWatcher { /** * 删除按钮的引用 */ private Drawable mClearDrawable; public ClearEditText(Context context) { this(context, null); } public ClearEditText(Context context, AttributeSet attrs) { //这里构造方法也很重要,不加这个很多属性不能再XML里面定义 this(context, attrs, android.R.attr.editTextStyle); } public ClearEditText(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(); } private void init() { //获取EditText的DrawableRight,假如没有设置我们就使用默认的图片 mClearDrawable = getCompoundDrawables()[2]; if (mClearDrawable == null) { mClearDrawable = getResources() .getDrawable(R.drawable.emotionstore_progresscancelbtn); } mClearDrawable.setBounds(0, 0, mClearDrawable.getIntrinsicWidth(), mClearDrawable.getIntrinsicHeight()); setClearIconVisible(false); setOnFocusChangeListener(this); addTextChangedListener(this); } /** * 因为我们不能直接给EditText设置点击事件,所以我们用记住我们按下的位置来模拟点击事件 * 当我们按下的位置 在 EditText的宽度 - 图标到控件右边的间距 - 图标的宽度 和 * EditText的宽度 - 图标到控件右边的间距之间我们就算点击了图标,竖直方向没有考虑 */ @Override public boolean onTouchEvent(MotionEvent event) { if (getCompoundDrawables()[2] != null) { if (event.getAction() == MotionEvent.ACTION_UP) { boolean touchable = event.getX() > (getWidth() - getPaddingRight() - mClearDrawable.getIntrinsicWidth()) && (event.getX() < ((getWidth() - getPaddingRight()))); if (touchable) { this.setText(""); } } } return super.onTouchEvent(event); } /** * 当ClearEditText焦点发生变化的时候,判断里面字符串长度设置清除图标的显示与隐藏 */ @Override public void onFocusChange(View v, boolean hasFocus) { if (hasFocus) { setClearIconVisible(getText().length() > 0); } else { setClearIconVisible(false); } } /** * 设置清除图标的显示与隐藏,调用setCompoundDrawables为EditText绘制上去 * @param visible */ protected void setClearIconVisible(boolean visible) { Drawable right = visible ? mClearDrawable : null; setCompoundDrawables(getCompoundDrawables()[0], getCompoundDrawables()[1], right, getCompoundDrawables()[3]); } /** * 当输入框里面内容发生变化的时候回调的方法 */ @Override public void onTextChanged(CharSequence s, int start, int count, int after) { setClearIconVisible(s.length() > 0); } @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void afterTextChanged(Editable s) { } /** * 设置晃动动画 */ public void setShakeAnimation(){ this.setAnimation(shakeAnimation(5)); } /** * 晃动动画 * @param counts 1秒钟晃动多少下 * @return */ public static Animation shakeAnimation(int counts){ Animation translateAnimation = new TranslateAnimation(0, 10, 0, 0); translateAnimation.setInterpolator(new CycleInterpolator(counts)); translateAnimation.setDuration(1000); return translateAnimation; } }
右侧字母侧边框 sideBar
package com.example.sortlistview; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Typeface; import android.graphics.drawable.ColorDrawable; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; import android.widget.TextView; public class SideBar extends View { // 触摸事件 private OnTouchingLetterChangedListener onTouchingLetterChangedListener; // 26个字母 public static String[] b = { "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 int choose = -1;// 选中 private Paint paint = new Paint(); private TextView mTextDialog; public void setTextView(TextView mTextDialog) { this.mTextDialog = mTextDialog; } public SideBar(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } public SideBar(Context context, AttributeSet attrs) { super(context, attrs); } public SideBar(Context context) { super(context); } /** * 重写这个方法 */ protected void onDraw(Canvas canvas) { super.onDraw(canvas); // 获取焦点改变背景颜色. int height = getHeight();// 获取对应高度 int width = getWidth(); // 获取对应宽度 int singleHeight = height / b.length;// 获取每一个字母的高度 canvas.drawColor(Color.argb(0,0,0,0)); for (int i = 0; i < b.length; i++) { paint.setColor(Color.rgb(33, 65, 98)); paint.setTypeface(Typeface.DEFAULT_BOLD); paint.setAntiAlias(true); paint.setTextSize(20); // 选中的状态 if (i == choose) { paint.setColor(Color.parseColor("#3399ff")); paint.setFakeBoldText(true); } // x坐标等于中间-字符串宽度的一半. float xPos = width / 2 - paint.measureText(b[i]) / 2; float yPos = singleHeight * i + singleHeight; canvas.drawText(b[i], xPos, yPos, paint); paint.reset();// 重置画笔 } } @Override public boolean dispatchTouchEvent(MotionEvent event) { final int action = event.getAction(); final float y = event.getY();// 点击y坐标 final int oldChoose = choose; final OnTouchingLetterChangedListener listener = onTouchingLetterChangedListener; final int c = (int) (y / getHeight() * b.length);// 点击y坐标所占总高度的比例*b数组的长度就等于点击b中的个数. switch (action) { case MotionEvent.ACTION_UP: setBackgroundDrawable(new ColorDrawable(0x00000000)); // choose = -1; // invalidate(); if (mTextDialog != null) { mTextDialog.setVisibility(View.INVISIBLE); } break; default: setBackgroundDrawable(new ColorDrawable(0x00000000)); if (oldChoose != c) { if (c >= 0 && c < b.length) { if (listener != null) { listener.onTouchingLetterChanged(b[c]); } if (mTextDialog != null) { mTextDialog.setText(b[c]); mTextDialog.setVisibility(View.VISIBLE); } choose = c; invalidate(); } } break; } return true; } /** * 向外公开的方法 * * @param onTouchingLetterChangedListener */ public void setOnTouchingLetterChangedListener( OnTouchingLetterChangedListener onTouchingLetterChangedListener) { this.onTouchingLetterChangedListener = onTouchingLetterChangedListener; } /** * 接口 * * @author coder * */ public interface OnTouchingLetterChangedListener { public void onTouchingLetterChanged(String s); } }
联系人没有首字母特殊处理 PinyinComparator
package com.example.sortlistview; import java.util.Comparator; /** * 联系人没有首字母特殊处理 * @author Administrator * */ public class PinyinComparator implements Comparator<SortModel> { public int compare(SortModel o1, SortModel o2) { if (o1.getSortLetters().equals("@") || o2.getSortLetters().equals("#")) { return -1; } else if (o1.getSortLetters().equals("#") || o2.getSortLetters().equals("@")) { return 1; } else { return o1.getSortLetters().compareTo(o2.getSortLetters()); } } }
联系人对象 SortModel
package com.example.sortlistview; public class SortModel { private String name; //显示的数据 private String mobile; private String sortLetters; //显示数据拼音的首字母 public String getName() { return name; } public void setName(String name) { this.name = name; } public String getSortLetters() { return sortLetters; } public void setSortLetters(String sortLetters) { this.sortLetters = sortLetters; } public String getMobile() { return mobile; } public void setMobile(String mobile) { this.mobile = mobile; } }
数据显示格式定义类 SortAdapter
package com.example.sortlistview; import java.util.List; import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.SectionIndexer; import android.widget.TextView; public class SortAdapter extends BaseAdapter implements SectionIndexer{ private List<SortModel> list = null; private Context mContext; public SortAdapter(Context mContext, List<SortModel> list) { this.mContext = mContext; this.list = list; } /** * 当ListView数据发生变化时,调用此方法来更新ListView * @param list */ public void updateListView(List<SortModel> list){ this.list = list; notifyDataSetChanged(); } public int getCount() { return this.list.size(); } public Object getItem(int position) { return list.get(position); } public long getItemId(int position) { return position; } public View getView(final int position, View view, ViewGroup arg2) { ViewHolder viewHolder = null; final SortModel mContent = list.get(position); if (view == null) { viewHolder = new ViewHolder(); view = LayoutInflater.from(mContext).inflate(R.layout.item, null); viewHolder.tvTitle = (TextView) view.findViewById(R.id.title); viewHolder.tvLetter = (TextView) view.findViewById(R.id.catalog); viewHolder.tvPhone = (TextView) view.findViewById(R.id.phone); view.setTag(viewHolder); } else { viewHolder = (ViewHolder) view.getTag(); } //根据position获取分类的首字母的Char ascii值 int section = getSectionForPosition(position); //如果当前位置等于该分类首字母的Char的位置 ,则认为是第一次出现 if(position == getPositionForSection(section)){ viewHolder.tvLetter.setVisibility(View.VISIBLE); viewHolder.tvLetter.setText(mContent.getSortLetters()); }else{ viewHolder.tvLetter.setVisibility(View.GONE); } SortModel sort = this.list.get(position); viewHolder.tvTitle.setText(sort.getName()); viewHolder.tvPhone.setText(sort.getMobile()); return view; } final static class ViewHolder { TextView tvLetter; TextView tvTitle; TextView tvPhone; } /** * 根据ListView的当前位置获取分类的首字母的Char ascii值 */ public int getSectionForPosition(int position) { return list.get(position).getSortLetters().charAt(0); } /** * 根据分类的首字母的Char ascii值获取其第一次出现该首字母的位置 */ public int getPositionForSection(int section) { for (int i = 0; i < getCount(); i++) { String sortStr = list.get(i).getSortLetters(); char firstChar = sortStr.toUpperCase().charAt(0); if (firstChar == section) { return i; } } return -1; } /** * 提取英文的首字母,非英文字母用#代替。 * * @param str * @return */ private String getAlpha(String str) { String sortStr = str.trim().substring(0, 1).toUpperCase(); // 正则表达式,判断首字母是否是英文字母 if (sortStr.matches("[A-Z]")) { return sortStr; } else { return "#"; } } @Override public Object[] getSections() { return null; } }
主页activity布局文件
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <com.example.sortlistview.ClearEditText android:id="@+id/filter_edit" android:layout_marginTop="5dip" android:layout_width="fill_parent" android:layout_height="wrap_content" android:background="@drawable/search_bar_edit_selector" android:drawableLeft="@drawable/search_bar_icon_normal" android:hint="请输入关键字" android:singleLine="true" android:textSize="15.0dip" /> <FrameLayout android:layout_width="fill_parent" android:layout_height="fill_parent" > <ListView android:id="@+id/country_lvcountry" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_gravity="center" android:divider="@null" /> <TextView android:id="@+id/dialog" android:layout_width="80.0dip" android:layout_height="80.0dip" android:layout_gravity="center" android:background="@drawable/show_head_toast_bg" android:gravity="center" android:textColor="#ffffffff" android:textSize="30.0dip" android:visibility="invisible" /> <com.example.sortlistview.SideBar android:id="@+id/sidrbar" android:layout_width="30.0dip" android:layout_height="fill_parent" android:layout_gravity="right|center" /> </FrameLayout> </LinearLayout>
数据显示item 布局文件
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content" android:gravity="center_vertical" android:orientation="vertical" > <TextView android:id="@+id/catalog" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="#E0E0E0" android:textColor="#454545" android:layout_weight="1.0" android:paddingLeft="5dip" android:paddingTop="5dip" android:paddingBottom="5dip" android:text="A"/> <LinearLayout android:id="@+id/contachInfo" android:layout_width="fill_parent" android:layout_height="50dip" android:gravity="center_vertical" android:orientation="horizontal" > <ImageView android:id="@+id/imgHead" android:layout_width="40dip" android:layout_height="40dip" android:src="@drawable/default_avatar" android:paddingLeft="5dip" /> <LinearLayout android:id="@+id/phoneLayout" android:layout_width="fill_parent" android:layout_height="fill_parent" android:gravity="center_vertical" android:orientation="vertical" android:paddingLeft="5dip" android:layout_marginLeft="5dip" > <TextView android:id="@+id/title" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_gravity="center_vertical" android:gravity="bottom" android:layout_weight="1.0" android:textColor="#000000" android:textSize="12sp" android:text="hhhh"/> <TextView android:id="@+id/phone" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_gravity="center_vertical" android:gravity="center_vertical" android:layout_weight="1.0" android:textColor="#000000" android:textSize="12sp" android:text="电话号码"/> </LinearLayout> </LinearLayout> </LinearLayout>
活动窗口:
package com.example.sortlistview; import java.util.ArrayList; import java.util.Collections; import java.util.List; import android.app.Activity; import android.content.ContentResolver; import android.database.Cursor; import android.os.Bundle; import android.provider.ContactsContract.CommonDataKinds.Phone; import android.provider.ContactsContract.Contacts.Photo; import android.text.Editable; import android.text.TextUtils; import android.text.TextWatcher; import android.view.View; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.ListView; import android.widget.TextView; import android.widget.Toast; import com.example.sortlistview.SideBar.OnTouchingLetterChangedListener; public class MainActivity extends Activity { private ListView sortListView; private SideBar sideBar; private TextView dialog; private SortAdapter adapter; private ClearEditText mClearEditText; /** * 汉字转换成拼音的类 */ private CharacterParser characterParser; private List<SortModel> SourceDateList; /** * 根据拼音来排列ListView里面的数据类 */ private PinyinComparator pinyinComparator; /** 联系人显示名称 **/ private static final int PHONES_DISPLAY_NAME_INDEX = 0; /** 电话号码 **/ private static final int PHONES_NUMBER_INDEX = 1; /** 头像ID **/ // private static final int PHONES_PHOTO_ID_INDEX = 2; /** 联系人的ID **/ // private static final int PHONES_CONTACT_ID_INDEX = 3; /** 库 phone表字段 **/ private static final String[] PHONES_PROJECTION = new String[] { Phone.DISPLAY_NAME, Phone.NUMBER, Photo.PHOTO_ID, Phone.CONTACT_ID }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initViews(); } private void initViews() { //实例化汉字转拼音类 characterParser = CharacterParser.getInstance(); pinyinComparator = new PinyinComparator(); sideBar = (SideBar) findViewById(R.id.sidrbar); dialog = (TextView) findViewById(R.id.dialog); sideBar.setTextView(dialog); //设置右侧触摸监听 sideBar.setOnTouchingLetterChangedListener(new OnTouchingLetterChangedListener() { @Override public void onTouchingLetterChanged(String s) { //该字母首次出现的位置 int position = adapter.getPositionForSection(s.charAt(0)); if(position != -1){ sortListView.setSelection(position); } } }); sortListView = (ListView) findViewById(R.id.country_lvcountry); sortListView.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { //这里要利用adapter.getItem(position)来获取当前position所对应的对象 Toast.makeText(getApplication(), ((SortModel)adapter.getItem(position)).getName(), Toast.LENGTH_SHORT).show(); } }); SourceDateList = loadPhoneContactData(); // 根据a-z进行排序源数据 Collections.sort(SourceDateList, pinyinComparator); adapter = new SortAdapter(this, SourceDateList); sortListView.setAdapter(adapter); mClearEditText = (ClearEditText) findViewById(R.id.filter_edit); //根据输入框输入值的改变来过滤搜索 mClearEditText.addTextChangedListener(new TextWatcher() { @Override public void onTextChanged(CharSequence s, int start, int before, int count) { //当输入框里面的值为空,更新为原来的列表,否则为过滤数据列表 filterData(s.toString()); } @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void afterTextChanged(Editable s) { } }); } /** * 加载手机联系人 */ private List<SortModel> loadPhoneContactData() { List<SortModel> mSortList = new ArrayList<SortModel>(); ContentResolver resolver = this.getContentResolver(); Cursor phoneCursor = resolver.query(Phone.CONTENT_URI, PHONES_PROJECTION, null, null, null); SortModel sort = null; String phoneNumber = ""; String phoneName = ""; // Long photoID = 0l; if (phoneCursor != null) { while (phoneCursor.moveToNext()) { // get phone number phoneNumber = phoneCursor.getString(PHONES_NUMBER_INDEX) .replace(" ", ""); if (phoneNumber==null||phoneNumber=="") continue; phoneName = phoneCursor.getString(PHONES_DISPLAY_NAME_INDEX); sort = new SortModel(); sort.setMobile(phoneNumber); sort.setName(phoneName); // 汉字转换成拼音 String pinyin = characterParser.getSelling(phoneName); String sortString = pinyin.substring(0, 1).toUpperCase(); sort.setSortLetters(sortString); // 正则表达式,判断首字母是否是英文字母 if (sortString.matches("[A-Z]")) { sort.setSortLetters(sortString.toUpperCase()); } else { sort.setSortLetters("#"); } mSortList.add(sort); } phoneCursor.close(); } return mSortList; } /** * 根据输入框中的值来过滤数据并更新ListView * @param filterStr */ private void filterData(String filterStr){ List<SortModel> filterDateList = new ArrayList<SortModel>(); if(TextUtils.isEmpty(filterStr)){ filterDateList = SourceDateList; }else{ filterDateList.clear(); for(SortModel sortModel : SourceDateList){ String name = sortModel.getName(); if(name.indexOf(filterStr.toString()) != -1 || characterParser.getSelling(name).startsWith(filterStr.toString())){ filterDateList.add(sortModel); } } } // 根据a-z进行排序 Collections.sort(filterDateList, pinyinComparator); adapter.updateListView(filterDateList); } }
AndroidManifest.xml文件,说明一下,获取手机通讯录,必须添加通讯录访问权限;即
<uses-permission android:name="android.permission.READ_CONTACTS" />
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.sortlistview" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="23" /> <uses-permission android:name="android.permission.READ_CONTACTS" /> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name="com.example.sortlistview.MainActivity" android:windowSoftInputMode = "adjustPan" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
运行效果图:
相关文章推荐
- Android手势识别ViewFlipper触摸动画
- Android studio 报一下错时解决方案For example, the following line, in the gradle.properties file, sets the max
- Android动画之Property属性动画
- Android Studio多渠道签名打包
- 将RecyclerView的宽高属性设置为“wrap_content”
- android抽屉实现
- android开发中的九宫格布局的实现
- Android活动的四种启动方式(standard singleTop singleTask singleInstance)
- Android应用打破65K方法数限制,让你的应用不再爆棚
- Android While 循环导致的资源占用过高进而导致程序崩溃问题
- Android 基本控件的使用三(RadioButton)
- 2015最流行的Android组件、工具、框架大全
- Toast的其他用法(带图片的toast)
- android sql 数据类型
- android 调用系统相机,不拍照直接按返回的处理。
- Android练习(二)
- Android SDK Manager国内无法更新的解决方案(亲测有效)
- Android学习路线指南
- Android一个自定义的进度环:ProgressChart
- android6.0 adbd深入分析(五)adbd处理adb root的一个bug