以下代碼經過測試,可以通過,無需下載,只要照着執行就可以run
注意:
androidmanifest.xml文件中添加以下權限
<uses-permission android:name="android.permission.READ_CONTACTS" />
注意正則表達式的那塊代碼,很多轉載的文章那裏代碼直接ctrl+c是錯誤的
解惑:
當你電話本中沒有數據的時候,應該沒有數據;當電話本中沒有P打頭的,你現在點擊P導航,也是無法切的P的位置,其他字母類似。
1.FastContactSearchDemoActivity.java
- package com.zhf.FastContactSearchWithAlphabeticBarDemo;
- import java.util.ArrayList;
- import java.util.Collections;
- import java.util.HashMap;
- import java.util.List;
- import java.util.Set;
- import java.util.regex.Pattern;
- import com.zhf.FastContactSearchDemo.R;
- import android.app.Activity;
- import android.content.AsyncQueryHandler;
- import android.content.ContentResolver;
- import android.content.ContentValues;
- import android.content.Context;
- import android.database.Cursor;
- import android.net.Uri;
- import android.os.Bundle;
- import android.view.LayoutInflater;
- import android.view.View;
- import android.view.ViewGroup;
- import android.widget.BaseAdapter;
- import android.widget.ListView;
- import android.widget.TextView;
- /**
- * 聯繫人分章節顯示、ListView快速滑動顯示聯繫人首字母、附帶字母表快速查找的例子
- * 查閱網絡資源,實現方式都是比較複雜,尤其有些還實現了SectionIndex接口,很多人不怎麼能理解,研究後發現此種類型的例子沒必要也不應該那麼實現
- * @author [email protected]
- *
- */
- public class FastContactSearchDemoActivity extends Activity {
- private BaseAdapter adapter;
- private ListView personList;
- private List<ContentValues> list;
- private AsyncQueryHandler asyncQuery;
- private QuickAlphabeticBar alpha;
- private static final String NAME = "name", NUMBER = "number",
- SORT_KEY = "sort_key";
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- personList = (ListView) findViewById(R.id.listView);
- alpha = (QuickAlphabeticBar) findViewById(R.id.fast_scroller);
- asyncQuery = new MyAsyncQueryHandler(getContentResolver());
- }
- @Override
- protected void onResume() {
- super.onResume();
- Uri uri = Uri.parse("content://com.android.contacts/data/phones"); // 聯繫人的Uri
- String[] projection = { "_id", "display_name", "data1", "sort_key" }; // 查詢的列
- asyncQuery.startQuery(0, null, uri, projection, null, null,
- "sort_key COLLATE LOCALIZED asc"); // 按照sort_key升序查詢
- }
- /**
- * 數據庫異步查詢類AsyncQueryHandler
- *
- * @author administrator
- *
- */
- private class MyAsyncQueryHandler extends AsyncQueryHandler {
- public MyAsyncQueryHandler(ContentResolver cr) {
- super(cr);
- }
- /**
- * 查詢結束的回調函數
- */
- @Override
- protected void onQueryComplete(int token, Object cookie, Cursor cursor) {
- if (cursor != null && cursor.getCount() > 0) {
- list = new ArrayList<ContentValues>();
- cursor.moveToFirst();
- for (int i = 0; i < cursor.getCount(); i++) {
- ContentValues cv = new ContentValues();
- cursor.moveToPosition(i);
- String name = cursor.getString(1);
- String number = cursor.getString(2);
- String sortKey = cursor.getString(3);
- if (number.startsWith("+86")) {// 去除多餘的中國地區號碼標誌,對這個程序沒有影響。
- cv.put(NAME, name);
- cv.put(NUMBER, number.substring(3));
- cv.put(SORT_KEY, sortKey);
- } else {
- cv.put(NAME, name);
- cv.put(NUMBER, number);
- cv.put(SORT_KEY, sortKey);
- }
- list.add(cv);
- }
- if (list.size() > 0) {
- setAdapter(list);
- }
- }
- }
- }
- private void setAdapter(List<ContentValues> list) {
- adapter = new ListAdapter(this, list);
- personList.setAdapter(adapter);
- alpha.init(FastContactSearchDemoActivity.this);
- alpha.setListView(personList);
- alpha.setHight(alpha.getHeight());
- alpha.setVisibility(View.VISIBLE);
- }
- private static class ViewHolder {
- TextView alpha;
- TextView name;
- TextView number;
- }
- /*
- * 移植時只需要提供一個已排序的集合list即可
- */
- private class ListAdapter extends BaseAdapter{
- private LayoutInflater inflater;
- private List<ContentValues> list;
- private HashMap<String, Integer> alphaIndexer;//保存每個索引在list中的位置【#-0,A-4,B-10】
- private String[] sections;//每個分組的索引表【A,B,C,F...】
- public ListAdapter(Context context, List<ContentValues> list) {
- this.inflater = LayoutInflater.from(context);
- this.list = list; // 該list是已經排序過的集合,有些項目中的數據必須要自己進行排序。
- this.alphaIndexer = new HashMap<String, Integer>();
- this.sections = new String[list.size()];
- for (int i =0; i <list.size(); i++) {
- String name = getAlpha(list.get(i).getAsString(SORT_KEY));
- if(!alphaIndexer.containsKey(name)){//只記錄在list中首次出現的位置
- alphaIndexer.put(name, i);
- }
- }
- Set<String> sectionLetters = alphaIndexer.keySet();
- ArrayList<String> sectionList = new ArrayList<String>(
- sectionLetters);
- Collections.sort(sectionList);
- sections = new String[sectionList.size()];
- sectionList.toArray(sections);
- alpha.setAlphaIndexer(alphaIndexer);
- }
- @Override
- public int getCount() {
- return list.size();
- }
- @Override
- public Object getItem(int position) {
- return list.get(position);
- }
- @Override
- public long getItemId(int position) {
- return position;
- }
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- ViewHolder holder;
- if (convertView == null) {
- convertView = inflater.inflate(R.layout.list_item, null);
- holder = new ViewHolder();
- holder.alpha = (TextView) convertView.findViewById(R.id.alpha);
- holder.name = (TextView) convertView.findViewById(R.id.name);
- holder.number = (TextView) convertView
- .findViewById(R.id.number);
- convertView.setTag(holder);
- } else {
- holder = (ViewHolder) convertView.getTag();
- }
- ContentValues cv = list.get(position);
- String name = cv.getAsString(NAME);
- String number = cv.getAsString(NUMBER);
- holder.name.setText(name);
- holder.number.setText(number);
- // 當前聯繫人的sortKey
- String currentStr = getAlpha(list.get(position).getAsString(
- SORT_KEY));
- // 上一個聯繫人的sortKey
- String previewStr = (position - 1) >= 0 ? getAlpha(list.get(
- position - 1).getAsString(SORT_KEY)) : " ";
- /**
- * 判斷顯示#、A-Z的TextView隱藏與可見
- */
- if (!previewStr.equals(currentStr)) { // 當前聯繫人的sortKey!=上一個聯繫人的sortKey,說明當前聯繫人是新組。
- holder.alpha.setVisibility(View.VISIBLE);
- holder.alpha.setText(currentStr);
- } else {
- holder.alpha.setVisibility(View.GONE);
- }
- return convertView;
- }
- }
- /**
- * 提取英文的首字母,非英文字母用#代替。
- *
- * @param str
- * @return
- */
- private String getAlpha(String str) {
- if (str == null) {
- return "#";
- }
- if (str.trim().length() == 0) {
- return "#";
- }
- char c = str.trim().substring(0, 1).charAt(0);
- // 正則表達式,判斷首字母是否是英文字母
- Pattern pattern = Pattern.compile("^[A-Za-z]+$");
- if (pattern.matcher(c + "").matches()) {
- return (c + "").toUpperCase(); // 大寫輸出
- } else {
- return "#";
- }
- }
- }
2.QuickAlphabeticBar.java
- package com.zhf.FastContactSearchWithAlphabeticBarDemo;
- import java.util.HashMap;
- import com.zhf.FastContactSearchDemo.R;
- import android.app.Activity;
- import android.content.Context;
- import android.os.Handler;
- import android.util.AttributeSet;
- import android.view.MotionEvent;
- import android.view.View;
- import android.widget.ImageButton;
- import android.widget.ListView;
- import android.widget.TextView;
- /**
- * 字母表
- * @author [email protected]
- *
- */
- public class QuickAlphabeticBar extends ImageButton {
- private TextView mDialogText;
- private Handler mHandler;
- private ListView mList;
- private float mHight;
- private String[] letters = new String[] { "#", "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 HashMap<String, Integer> alphaIndexer;
- public QuickAlphabeticBar(Context context) {
- super(context);
- }
- public QuickAlphabeticBar(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
- public QuickAlphabeticBar(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- }
- public void init(Activity ctx) {
- mDialogText = (TextView) ctx.findViewById(R.id.fast_position);
- mDialogText.setVisibility(View.INVISIBLE);
- mHandler = new Handler();
- }
- public void setListView(ListView mList) {
- this.mList = mList;
- }
- public void setAlphaIndexer(HashMap<String, Integer> alphaIndexer) {
- this.alphaIndexer = alphaIndexer;
- }
- public void setHight(float mHight) {
- this.mHight = mHight;
- }
- @Override
- public boolean onTouchEvent(MotionEvent event) {
- int act = event.getAction();
- float y = event.getY();
- // 計算手指位置,找到對應的段,讓mList移動段開頭的位置上
- int selectIndex = (int) (y / (mHight / 27));
- if (selectIndex < 27) {// 防止越界
- String key = letters[selectIndex];
- if (alphaIndexer.containsKey(key)) {
- int pos = alphaIndexer.get(key);
- if (mList.getHeaderViewsCount() > 0) {// 防止ListView有標題欄,本例中沒有。
- this.mList.setSelectionFromTop(
- pos + mList.getHeaderViewsCount(), 0);
- } else {
- this.mList.setSelectionFromTop(pos, 0);
- }
- mDialogText.setText(letters[selectIndex]);
- }
- }
- if (act == MotionEvent.ACTION_DOWN) {
- if (mHandler != null) {
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- if (mDialogText != null
- && mDialogText.getVisibility() == View.INVISIBLE) {
- mDialogText.setVisibility(VISIBLE);
- }
- }
- });
- }
- } else if (act == MotionEvent.ACTION_UP) {
- if (mHandler != null) {
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- if (mDialogText != null
- && mDialogText.getVisibility() == View.VISIBLE) {
- mDialogText.setVisibility(INVISIBLE);
- }
- }
- });
- }
- }
- return super.onTouchEvent(event);
- }
- }
3.佈局文件
3.1.main.xml
- <?xml version="1.0" encoding="utf-8"?>
- <RelativeLayout android:layout_width="fill_parent"
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_height="fill_parent" android:layout_weight="1.0">
- <ListView android:id="@+id/listView"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:scrollbars="none"
- android:layout_weight="1.0"
- android:scrollingCache="true"
- >
- </ListView>
- <com.zhf.FastContactSearchWithAlphabeticBarDemo.QuickAlphabeticBar
- android:layout_alignRight="@id/listView"
- android:layout_gravity="top|right|center"
- android:layout_marginTop="10dip"
- android:id="@+id/fast_scroller" android:background="@null"
- android:layout_width="wrap_content" android:layout_height="wrap_content"
- android:scaleType="centerInside"
- android:src="@drawable/dic_background" />
- <TextView
- android:layout_centerInParent="true"
- android:id="@+id/fast_position" android:textSize="48dip" android:visibility="invisible"
- android:textColor="#404040" android:background="@drawable/sort_icon_bg_click"
- android:layout_gravity="center_horizontal|top" android:padding="2dip"
- android:layout_margin="34dip" android:layout_width="70dip"
- android:layout_height="70dip" android:gravity="center" />
- </RelativeLayout>
3.2.list_item.xml
- <?xml version="1.0" encoding="utf-8"?>
- <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent" >
- <!-- 首字母 -->
- <TextView
- android:id="@+id/alpha"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:background="#333333"
- android:paddingLeft="10dip"
- android:textColor="#FFFFFF"
- android:visibility="gone" />
- <!-- 聯繫人信息 -->
- <ImageView
- android:id="@+id/imageView"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentLeft="true"
- android:layout_below="@id/alpha"
- android:src="@drawable/ic_launcher" />
- <TextView
- android:id="@+id/name"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignTop="@id/imageView"
- android:layout_marginLeft="2.0dip"
- android:layout_marginRight="5.0dip"
- android:layout_marginTop="6.0dip"
- android:layout_toRightOf="@id/imageView"
- android:singleLine="true"
- android:textAppearance="?android:textAppearanceMedium" />
- <TextView
- android:id="@+id/number"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignLeft="@id/name"
- android:layout_alignWithParentIfMissing="true"
- android:layout_below="@id/name"
- android:ellipsize="marquee"
- android:singleLine="true"
- android:textAppearance="?android:textAppearanceSmall" />
- </RelativeLayout>
dic_background.xml
<?xml version="1.0" encoding="UTF-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:drawable="@drawable/a_z_click" />
<item android:state_focused="true" android:state_enabled="true"
android:drawable="@drawable/a_z_click" />
<item android:state_enabled="true" android:drawable="@drawable/a_z" />
</selector>
源碼地址:http://download.csdn.net/detail/zhf198909/4485281