首页 >> 大全

仿Android联系人SideBar排序,根据拼音A-Z字母快速导航联系人姓名

2023-08-30 大全 32 作者:考证青年

话不多说,直接上干货,图片如下:

这里写图片描述

仿联系人排序,通过获取手机中的联系人,并根据拼音A-Z字母快速导航联系人的位置,以及输入搜索条件过滤,显示姓名的文字图片。

这样的效果相信大家并不陌生,我们在APP中都司空见惯了,比如在选择地址的时候,选择国家,省份等等。这样的效果很多大神也都写过相应的博客,大体上实现的方式都差不多,今天我也给大家模仿一下联系人的排序实现。

1.首先我们把这几个工具类拷贝到自己的项目中,这些都是很常见的类:

–这是用来把中文转成拼音的工具类

–拼音首字母的比较器

–右侧的竖条,显示的是二十六个字母以及*,和#号

–放排序name和key的bean

2.加上一个来实现带删除当前输入内容按钮

在中输入内容,然后监听它的来实现搜索条件的过滤,具体代码见最下面的源码:

_联系人排序必须要按abc吗_联系人排序方式

3.接下来我们来看看实现这个效果改如何布局,看一下我们的布局文件:


<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent" android:focusableInTouchMode="true"><LinearLayout
        android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical" ><com.finddreams.sortedcontact.ClearEditText
            android:id="@+id/filter_edit"android:layout_width="fill_parent"android:layout_height="40dp"android:layout_marginLeft="5dp"android:layout_marginRight="5dp"android:layout_marginTop="5dip"android:gravity="center"android:background="@drawable/acm_inputbox"android:drawableLeft="@drawable/search"android:hint="@string/search"android:singleLine="true"android:textSize="15.0dip" /><FrameLayout
            android:layout_width="fill_parent"android:layout_height="wrap_content" ><ListView
                android:id="@+id/sortlist"android:layout_width="fill_parent"android:layout_height="fill_parent"android:background="@color/whites"android:listSelector="@drawable/comm_btn_selector"android:layout_gravity="center" /><TextView
                android:id="@+id/dialog"android:layout_width="80.0dip"android:layout_height="80.0dip"android:layout_gravity="center"android:background="@drawable/number_base"android:gravity="center"android:textColor="#ffffffff"android:textSize="30.0dip"android:visibility="invisible" /><com.finddreams.sortedcontact.sortlist.SideBar
                android:id="@+id/sidrbar"android:layout_width="30.0dip"android:layout_height="fill_parent"android:layout_gravity="right|center" />FrameLayout>LinearLayout>RelativeLayout>

4.然后我们就可以在代码中调用了,具体的代码如下:

/*** @Description:联系人显示界面* @author http://blog.csdn.net/finddreams*/
public class MainActivity extends Activity {private View mBaseView;private ListView sortListView;private SideBar sideBar;private TextView dialog;private SortAdapter adapter;private ClearEditText mClearEditText;private Map callRecords;private CharacterParser characterParser;private List SourceDateList;private PinyinComparator pinyinComparator;@Overrideprotected void onCreate(Bundle savedInstanceState) {// TODO Auto-generated method stubsuper.onCreate(savedInstanceState);setContentView(R.layout.activity_main_contact);initView();initData();}private void initView() {sideBar = (SideBar) this.findViewById(R.id.sidrbar);dialog = (TextView) this.findViewById(R.id.dialog);sortListView = (ListView) this.findViewById(R.id.sortlist);}private void initData() {// 实例化汉字转拼音类characterParser = CharacterParser.getInstance();pinyinComparator = new PinyinComparator();sideBar.setTextView(dialog);// 设置右侧触摸监听sideBar.setOnTouchingLetterChangedListener(new OnTouchingLetterChangedListener() {@SuppressLint("NewApi")@Overridepublic void onTouchingLetterChanged(String s) {// 该字母首次出现的位置int position = adapter.getPositionForSection(s.charAt(0));if (position != -1) {sortListView.setSelection(position);}}});sortListView.setOnItemClickListener(new OnItemClickListener() {@Overridepublic 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();String number = callRecords.get(((SortModel) adapter.getItem(position)).getName());Toast.makeText(MainActivity.this, number, 0).show();}});new ConstactAsyncTask().execute(0);}private class ConstactAsyncTask extendsAsyncTask {@Overrideprotected Integer doInBackground(Integer... arg0) {int result = -1;callRecords = ConstactUtil.getAllCallRecords(MainActivity.this);result = 1;return result;}@Overrideprotected void onPostExecute(Integer result) {super.onPostExecute(result);if (result == 1) {List constact = new ArrayList();for (Iterator keys = callRecords.keySet().iterator(); keys.hasNext();) {String key = keys.next();constact.add(key);}String[] names = new String[] {};names = constact.toArray(names);SourceDateList = filledData(names);// 根据a-z进行排序源数据Collections.sort(SourceDateList, pinyinComparator);adapter = new SortAdapter(MainActivity.this, SourceDateList);sortListView.setAdapter(adapter);mClearEditText = (ClearEditText) MainActivity.this.findViewById(R.id.filter_edit);mClearEditText.setOnFocusChangeListener(new OnFocusChangeListener() {@Overridepublic void onFocusChange(View arg0, boolean arg1) {mClearEditText.setGravity(Gravity.LEFT| Gravity.CENTER_VERTICAL);}});// 根据输入框输入值的改变来过滤搜索mClearEditText.addTextChangedListener(new TextWatcher() {@Overridepublic void onTextChanged(CharSequence s, int start,int before, int count) {// 当输入框里面的值为空,更新为原来的列表,否则为过滤数据列表filterData(s.toString());}@Overridepublic void beforeTextChanged(CharSequence s, int start,int count, int after) {}@Overridepublic void afterTextChanged(Editable s) {}});}}@Overrideprotected void onPreExecute() {super.onPreExecute();}}/*** 为ListView填充数据* * @param date* @return*/private List filledData(String[] date) {List mSortList = new ArrayList();for (int i = 0; i < date.length; i++) {SortModel sortModel = new SortModel();sortModel.setName(date[i]);// 汉字转换成拼音String pinyin = characterParser.getSelling(date[i]);String sortString = pinyin.substring(0, 1).toUpperCase();// 正则表达式,判断首字母是否是英文字母if (sortString.matches("[A-Z]")) {sortModel.setSortLetters(sortString.toUpperCase());} else {sortModel.setSortLetters("#");}mSortList.add(sortModel);}return mSortList;}/*** 根据输入框中的值来过滤数据并更新ListView* * @param filterStr*/private void filterData(String filterStr) {List filterDateList = new ArrayList();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);}}

5.为了获取到联系人的数据,我们首先当然是不要忘了添加获取联系人的权限了,其次这里有一个获取联系人的工具类,十分的方便:

public class ConstactUtil {/*** 获取所有数据* * @return*/public static Map getAllCallRecords(Context context) {Map temp = new HashMap();Cursor c = context.getContentResolver().query(ContactsContract.Contacts.CONTENT_URI,null,null,null,ContactsContract.Contacts.DISPLAY_NAME+ " COLLATE LOCALIZED ASC");if (c.moveToFirst()) {do {// 获得联系人的ID号String contactId = c.getString(c.getColumnIndex(ContactsContract.Contacts._ID));// 获得联系人姓名String name = c.getString(c.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));// 查看该联系人有多少个电话号码。如果没有这返回值为0int phoneCount = c.getInt(c.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER));String number = null;if (phoneCount > 0) {// 获得联系人的电话号码Cursor phones = context.getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,null,ContactsContract.CommonDataKinds.Phone.CONTACT_ID+ " = " + contactId, null, null);if (phones.moveToFirst()) {number = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));}phones.close();}temp.put(name, number);} while (c.moveToNext());}c.close();return temp;}
}

6.我们来看看 是如何写的

/*** @Description:用来处理集合中数据的显示与排序* @author http://blog.csdn.net/finddreams*/
public class SortAdapter extends BaseAdapter implements SectionIndexer {private List list = null;private Context mContext;public SortAdapter(Context mContext, List list) {this.mContext = mContext;this.list = list;}/*** 当ListView数据发生变化时,调用此方法来更新ListView* * @param list*/public void updateListView(List 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.phone_constacts_item, null);viewHolder.tvTitle = (TextView) view.findViewById(R.id.title);viewHolder.tvLetter = (TextView) view.findViewById(R.id.catalog);viewHolder.icon = (ImageTextView) view.findViewById(R.id.icon);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);}viewHolder.tvTitle.setText(this.list.get(position).getName());viewHolder.icon.setText(this.list.get(position).getName());viewHolder.icon.setIconText(mContext, this.list.get(position).getName());return view;}final static class ViewHolder {TextView tvLetter;TextView tvTitle;ImageTextView icon;}/*** 根据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 "#";}}@Overridepublic Object[] getSections() {return null;}
}

7.为了实现每个名字前面带有这个名字中第一个字的图片,我们首先要引入一个自定义的类,它是继承自的,我们所做的只是在拿到这个的Text内容,然后根据这个内容画出一张图片,具体代码如下:

/**

* @: 文字图片,这个相信大家都知道,比如QQ底部导航上的未读消息数

联系人排序必须要按abc吗_联系人排序方式_

* @

*/

class {

;

text;

d;

public ImageTextView(Context context) {super(context);
}public ImageTextView(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);
}public ImageTextView(Context context, AttributeSet attrs) {super(context, attrs);
}public void setIconText(Context context, String text) {text = this.getText().toString().substring(0, 1);bitmap = BitmapUtil.getIndustry(context, text);d = BitmapUtil.bitmapTodrawable(bitmap);this.setCompoundDrawables(d, null, null, null);
}

其中有两个方法:

/*** 根据文字获取图片* @param text* @return*/public static Bitmap getIndustry(Context context, String text) {String color = "#ffeeeade";Bitmap src = BitmapFactory.decodeResource(context.getResources(),R.drawable.ic_launcher);int x = src.getWidth();int y = src.getHeight();Bitmap bmp = Bitmap.createBitmap(x, y, Bitmap.Config.ARGB_8888);Canvas canvasTemp = new Canvas(bmp);canvasTemp.drawColor(Color.parseColor(color));Paint p = new Paint(Paint.FAKE_BOLD_TEXT_FLAG | Paint.ANTI_ALIAS_FLAG);p.setColor(Color.parseColor("#ff4e0a13"));p.setAlpha(45);p.setFilterBitmap(true);int size = (int) (18 * context.getResources().getDisplayMetrics().density);p.setTextSize(size);float tX = (x - getFontlength(p, text)) / 2;float tY = (y - getFontHeight(p)) / 2 + getFontLeading(p);canvasTemp.drawText(text, tX, tY, p);return toRoundCorner(bmp, 2);}
/*** @param bitmap* @return*/public static Drawable bitmapTodrawable(Bitmap bitmap) {Drawable drawable = new BitmapDrawable(bitmap);drawable.setBounds(0, 0, bitmap.getWidth(), bitmap.getHeight());return drawable;}

这样就可以实现文字图片的效果了,是不是非常的简单。

最后需要的朋友可以去这里下载源码,学习学习:

关于我们

最火推荐

小编推荐

联系我们


版权声明:本站内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 88@qq.com 举报,一经查实,本站将立刻删除。备案号:桂ICP备2021009421号
Powered By Z-BlogPHP.
复制成功
微信号:
我知道了