Android 联系人列表界面(仿iphone、A~Z字母排列、过滤搜索)

来源:互联网 发布:手机截动图软件 编辑:程序博客网 时间:2024/06/05 23:02

前些天需要做一个联系人的列表界面,无奈网上的的demo都不太好看,而且有些bug也不少,只好自己借鉴着弄好了一个出来,顺便美化一下,感觉还是挺好看。

先看下效果是不是你想要的:

下载地址:http://download.csdn.net/detail/baiyulinlin1/9638852

                       

ContactsActivity.java

public class ContactsActivity extends Activity {ListView mListView;EditText etSearch;ImageView ivClearText;private SideBar sideBar;private TextView dialog;private List<SortModel> mAllContactsList;private ContactsSortAdapter adapter;Context mContext;/** * 汉字转换成拼音的类 */private CharacterParser characterParser;/** * 根据拼音来排列ListView里面的数据类 */private PinyinComparator pinyinComparator;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.layout_contacts);mContext = getApplicationContext();init();}private void init() {initView();initListener();loadContacts();}private void initListener() {/** 清除输入字符 **/ivClearText.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {etSearch.setText("");}});etSearch.addTextChangedListener(new TextWatcher() {@Overridepublic void onTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {}@Overridepublic void beforeTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {}@Overridepublic void afterTextChanged(Editable e) {String content = etSearch.getText().toString();if ("".equals(content)) {ivClearText.setVisibility(View.INVISIBLE);} else {ivClearText.setVisibility(View.VISIBLE);}if (content.length() > 0) {ArrayList<SortModel> fileterList = (ArrayList<SortModel>) search(content);adapter.updateListView(fileterList);// mAdapter.updateData(mContacts);} else {adapter.updateListView(mAllContactsList);}mListView.setSelection(0);}});// 设置右侧[A-Z]快速导航栏触摸监听sideBar.setOnTouchingLetterChangedListener(new OnTouchingLetterChangedListener() {@Overridepublic void onTouchingLetterChanged(String s) {// 该字母首次出现的位置int position = adapter.getPositionForSection(s.charAt(0));if (position != -1) {mListView.setSelection(position);}}});// item事件mListView.setOnItemClickListener(new OnItemClickListener() {@Overridepublic void onItemClick(AdapterView<?> adapterView, View view, int position, long arg3) {ViewHolder viewHolder = (ViewHolder) view.getTag();viewHolder.cbChecked.performClick();adapter.toggleChecked(position);}});}private void initView() {sideBar = (SideBar) findViewById(R.id.sidrbar);dialog = (TextView) findViewById(R.id.dialog);sideBar.setTextView(dialog);ivClearText = (ImageView) findViewById(R.id.ivClearText);etSearch = (EditText) findViewById(R.id.et_search);mListView = (ListView) findViewById(R.id.lv_contacts);/** 给ListView设置adapter **/characterParser = CharacterParser.getInstance();mAllContactsList = new ArrayList<SortModel>();pinyinComparator = new PinyinComparator();Collections.sort(mAllContactsList, pinyinComparator);// 根据a-z进行排序源数据adapter = new ContactsSortAdapter(this, mAllContactsList);mListView.setAdapter(adapter);}/** * 加载联系人数据 */private void loadContacts() {new Thread(new Runnable() {@Overridepublic void run() {try {// 插叙String queryTye[] = { Phone.DISPLAY_NAME, Phone.NUMBER, "sort_key", "phonebook_label",Phone.PHOTO_ID };ContentResolver resolver = getApplicationContext().getContentResolver();Cursor phoneCursor = resolver.query(Phone.CONTENT_URI, queryTye, null, null,"sort_key COLLATE LOCALIZED ASC");if (phoneCursor == null || phoneCursor.getCount() == 0) {Toast.makeText(getApplicationContext(), "未获得读取联系人权限 或 未获得联系人数据", Toast.LENGTH_SHORT).show();return;}int PHONES_NUMBER_INDEX = phoneCursor.getColumnIndex(Phone.NUMBER);int PHONES_DISPLAY_NAME_INDEX = phoneCursor.getColumnIndex(Phone.DISPLAY_NAME);int SORT_KEY_INDEX = phoneCursor.getColumnIndex("sort_key");int PHONEBOOK_LABEL = phoneCursor.getColumnIndex("phonebook_label");int PHOTO_ID = phoneCursor.getColumnIndex(Phone.PHOTO_ID);if (phoneCursor.getCount() > 0) {mAllContactsList = new ArrayList<SortModel>();while (phoneCursor.moveToNext()) {String phoneNumber = phoneCursor.getString(PHONES_NUMBER_INDEX);if (TextUtils.isEmpty(phoneNumber))continue;// 头像idlong photoId = phoneCursor.getLong(PHOTO_ID);String contactName = phoneCursor.getString(PHONES_DISPLAY_NAME_INDEX);String sortKey = phoneCursor.getString(SORT_KEY_INDEX);String book = phoneCursor.getString(PHONEBOOK_LABEL);SortModel sortModel = new SortModel(contactName, phoneNumber, sortKey);// //优先使用系统sortkey取,取不到再使用工具取// String sortLetters =// getSortLetterBySortKey(sortKey);// Log.i("main", "sortLetters:"+sortLetters);// if (sortLetters == null) {// sortLetters = getSortLetter(contactName);// }if (book == null) {book = "#";} else if (book.equals("#")) {book = "#";} else if (book.equals("")) {book = "#";}sortModel.sortLetters = book;sortModel.sortToken = parseSortKey(book);mAllContactsList.add(sortModel);}}phoneCursor.close();runOnUiThread(new Runnable() {public void run() {Collections.sort(mAllContactsList, pinyinComparator);adapter.updateListView(mAllContactsList);}});} catch (Exception e) {Log.e("xbc", e.getLocalizedMessage());}}}).start();}/** * 名字转拼音,取首字母 *  * @param name * @return */private String getSortLetter(String name) {String letter = "#";if (name == null) {return letter;}// 汉字转换成拼音// String pinyin = characterParser.getSelling(name);String pinyin = PinYin.getPinYin(name);Log.i("main", "pinyin:" + pinyin);String sortString = pinyin.substring(0, 1).toUpperCase(Locale.CHINESE);// 正则表达式,判断首字母是否是英文字母if (sortString.matches("[A-Z]")) {letter = sortString.toUpperCase(Locale.CHINESE);}return letter;}/** * 取sort_key的首字母 *  * @param sortKey * @return */private String getSortLetterBySortKey(String sortKey) {if (sortKey == null || "".equals(sortKey.trim())) {return null;}String letter = "#";// 汉字转换成拼音String sortString = sortKey.trim().substring(0, 1).toUpperCase(Locale.CHINESE);// 正则表达式,判断首字母是否是英文字母if (sortString.matches("[A-Z]")) {letter = sortString.toUpperCase(Locale.CHINESE);}return letter;}/** * 模糊查询 *  * @param str * @return */private List<SortModel> search(String str) {List<SortModel> filterList = new ArrayList<SortModel>();// 过滤后的list// if (str.matches("^([0-9]|[/+])*$")) {// 正则表达式 匹配号码if (str.matches("^([0-9]|[/+]).*")) {// 正则表达式// 匹配以数字或者加号开头的字符串(包括了带空格及-分割的号码)String simpleStr = str.replaceAll("\\-|\\s", "");for (SortModel contact : mAllContactsList) {if (contact.number != null && contact.name != null) {if (contact.simpleNumber.contains(simpleStr) || contact.name.contains(str)) {if (!filterList.contains(contact)) {filterList.add(contact);}}}}} else {for (SortModel contact : mAllContactsList) {if (contact.number != null && contact.name != null) {// 姓名全匹配,姓名首字母简拼匹配,姓名全字母匹配if (contact.name.toLowerCase(Locale.CHINESE).contains(str.toLowerCase(Locale.CHINESE))|| contact.sortKey.toLowerCase(Locale.CHINESE).replace(" ", "").contains(str.toLowerCase(Locale.CHINESE))|| contact.sortToken.simpleSpell.toLowerCase(Locale.CHINESE).contains(str.toLowerCase(Locale.CHINESE))|| contact.sortToken.wholeSpell.toLowerCase(Locale.CHINESE).contains(str.toLowerCase(Locale.CHINESE))) {if (!filterList.contains(contact)) {filterList.add(contact);}}}}}return filterList;}String chReg = "[\\u4E00-\\u9FA5]+";// 中文字符串匹配// String chReg="[^\\u4E00-\\u9FA5]";//除中文外的字符匹配/** * 解析sort_key,封装简拼,全拼 *  * @param sortKey * @return */public SortToken parseSortKey(String sortKey) {SortToken token = new SortToken();if (sortKey != null && sortKey.length() > 0) {// 其中包含的中文字符String[] enStrs = sortKey.replace(" ", "").split(chReg);for (int i = 0, length = enStrs.length; i < length; i++) {if (enStrs[i].length() > 0) {// 拼接简拼token.simpleSpell += enStrs[i].charAt(0);token.wholeSpell += enStrs[i];}}}return token;}}
SideBar.java 这个类就是侧边的A~Z的摆列,需要自定义的就修改这里

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;private float singleHeight;public static int dialogColor[] = { R.drawable.dialog_color_blue, R.drawable.dialog_color_green,R.drawable.dialog_color_orange, R.drawable.dialog_color_purple, R.drawable.dialog_color_red };;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(); // 获取对应宽度// 获取每一个字母的高度singleHeight = (height * 1f) / b.length;singleHeight = (height * 1f - singleHeight / 2) / b.length;for (int i = 0; i < b.length; i++) {paint.setColor(Color.rgb(23, 122, 216));// paint.setColor(Color.WHITE);paint.setTypeface(Typeface.DEFAULT_BOLD);paint.setAntiAlias(true);paint.setTextSize(25);// 选中的状态if (i == choose) {paint.setColor(Color.parseColor("#c60000"));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();// 重置画笔}}@Overridepublic 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:setBackgroundResource(R.drawable.sidebar_background);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);// 动态改变文字dialog的位置int right = mTextDialog.getLeft();mTextDialog.setX(right / 2 * 3);if(c>24){mTextDialog.setY(singleHeight * 24);}else{mTextDialog.setY(singleHeight * c);}mTextDialog.setBackground(getContext().getResources().getDrawable(dialogColor[c / 6]));}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);}}


0 0
原创粉丝点击