写道
有源码,在后面可以下载,这个方面的资料比较少,分享出来共同学习。
数据源是取出通讯录中的数据。
数据源是取出通讯录中的数据。
写道
AlphabetListView的实现:
package com.xiawenquan.test.widget;
import java.util.HashMap;
import android.content.Context;
import android.graphics.PixelFormat;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.xiawenquan.test.asyncqueryhandler.R;
import com.xiawenquan.test.widget.AlphabetView.OnTouchingLetterChangedListener;
public class AlphabetListView extends RelativeLayout {
private Context mContext;
private ListView mListView;
private AlphabetView mAlphabetView;
private HashMap<String, Integer> alphaIndexer;
private TextView overlay;
private Handler handler;
private OverlayThread overlayThread;
public AlphabetListView(Context context) {
super(context);
init(context);
}
public AlphabetListView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public AlphabetListView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context);
}
private void init(Context context) {
mContext = context;
LayoutInflater.from(context)
.inflate(R.layout.alphabet_list, this, true);
mListView = (ListView) findViewById(R.id.list_view);
mAlphabetView = (AlphabetView) findViewById(R.id.alphabet_view);
handler = new Handler();
overlayThread = new OverlayThread();
initOverlay();
mAlphabetView
.setOnTouchingLetterChangedListener(new OnTouchingLetterChangedListener() {
public void onTouchingLetterChanged(String s) {
if (alphaIndexer == null) {
// throw new
// RuntimeException("setAlphabetIndex方法未赋值");
} else {
final Integer position = alphaIndexer.get(s);
if (position != null) {
mListView.setSelection(position);
overlay.setText(s);
overlay.setVisibility(View.VISIBLE);
handler.removeCallbacks(overlayThread);
// 延迟一秒后执行,让overlay为不可见
handler.postDelayed(overlayThread, 1500);
} else if ("搜".equals(s)) {
mListView.setSelection(0);
overlay.setText(s);
overlay.setVisibility(View.VISIBLE);
handler.removeCallbacks(overlayThread);
// 延迟一秒后执行,让overlay为不可见
handler.postDelayed(overlayThread, 1500);
}
}
}
});
}
/**
* 设置首字母title再ListView中的位置
*
* @param alphaIndexer
*/
public void setAlphabetIndex(HashMap<String, Integer> alphaIndexer) {
this.alphaIndexer = alphaIndexer;
}
// 初始化汉语拼音首字母弹出提示框
private void initOverlay() {
final LayoutInflater inflater = LayoutInflater.from(mContext);
overlay = (TextView) inflater.inflate(R.layout.overlay, null);
overlay.setVisibility(View.INVISIBLE);
final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.TYPE_APPLICATION,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
| WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE,
PixelFormat.TRANSLUCENT);
final WindowManager windowManager = (WindowManager) mContext
.getSystemService(Context.WINDOW_SERVICE);
windowManager.addView(overlay, lp);
}
/**
* 设置overlay不可见
*/
public class OverlayThread implements Runnable {
public void run() {
overlay.setVisibility(View.GONE);
}
}
public void setListViewBackgroundResource(int resid) {
if (mListView != null) {
mListView.setBackgroundResource(resid);
}
}
public void setListViewBackgroundDrawable(Drawable d) {
if (mListView != null) {
mListView.setBackgroundDrawable(d);
}
}
public void setListViewDivider(Drawable divider) {
if (mListView != null) {
mListView.setDivider(divider);
}
}
public void setAdapter(BaseAdapter adapter) {
if (mListView != null) {
mListView.setAdapter(adapter);
}
}
public void setListViewsetVisibility(int visibility) {
if (mListView != null) {
mListView.setVisibility(visibility);
}
}
/**
* 设置字母列表默认颜色
*
* @param color
*/
public void setDefaultColor(int color) {
if (mAlphabetView != null) {
mAlphabetView.setDefaultColor(color);
}
}
/**
* 设置字母列表选中颜色
*
* @param color
*/
public void setSelectColor(int color) {
if (mAlphabetView != null) {
mAlphabetView.setSelectColor(color);
}
}
/**
* 设置字体大小
*
* @param size
*/
public void setTextSize(float size) {
if (mAlphabetView != null) {
mAlphabetView.setTextSize(size);
}
}
/**
* 设置搜索icon
*
* @param resid
*/
public void setSearchIcon(int resid) {
if (mAlphabetView != null) {
mAlphabetView.setSearchIcon(resid);
}
}
/**
* 设置搜索icon
*
* @param resid
*/
public void setSearchIcon(Drawable drawable) {
if (mAlphabetView != null) {
mAlphabetView.setSearchIcon(drawable);
}
}
/**
* 设置是否显示搜索icon
*
* @param isShowSearchIcon
*/
public void setShowSearchIcon(boolean isShowSearchIcon) {
if (mAlphabetView != null) {
mAlphabetView.setShowSearchIcon(isShowSearchIcon);
}
}
/**
* 设置索引浮窗字号
*
* @param size
*/
public void setOverlayTextSize(float size) {
if (overlay != null) {
overlay.setTextSize(size);
}
}
/**
* 设置索引浮窗字体颜色
*
* @param color
*/
public void setOverlayTextColor(int color) {
if (overlay != null) {
overlay.setTextColor(color);
}
}
/**
* 设置索引浮窗背景
*
* @param resId
*/
public void setOverlayBackground(int resid) {
if (overlay != null) {
overlay.setBackgroundResource(resid);
}
}
public void setOnItemClickListener(final OnItemClickListener listener) {
if (mListView != null) {
mListView
.setOnItemClickListener(new ListView.OnItemClickListener() {
public void onItemClick(AdapterView<?> arg0, View arg1,
int arg2, long arg3) {
if (listener != null) {
listener.onItemClick(arg0, arg1, arg2, arg3);
}
}
});
}
}
public void setOnItemLongClickListener(
final OnItemLongClickListener listener) {
if (mListView != null) {
mListView
.setOnItemLongClickListener(new ListView.OnItemLongClickListener() {
public boolean onItemLongClick(AdapterView<?> arg0,
View arg1, int arg2, long arg3) {
if (listener != null) {
listener.onItemLongClick(arg0, arg1, arg2, arg3);
}
return false;
}
});
}
}
public interface OnItemClickListener {
public void onItemClick(AdapterView<?> parent, View view, int position,
long id);
}
public interface OnItemLongClickListener {
public void onItemLongClick(AdapterView<?> parent, View view,
int position, long id);
}
public void setAlphabetViewVisibility(int visibility) {
if (mAlphabetView != null) {
mAlphabetView.setVisibility(visibility);
}
}
}
写道
AlphabetView 的实现:
package com.xiawenquan.test.widget;
import com.xiawenquan.test.asyncqueryhandler.R;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
public class AlphabetView extends View {
private Bitmap bitmap = null;
private OnTouchingLetterChangedListener onTouchingLetterChangedListener;
private int choose = -1;
private Paint paint = new Paint();
private boolean isShowSearchIcon = true;
private String[] alphabetList = { "#", "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 mDefaultColor = Color.parseColor("#6a737d");
private int mSelectColor = Color.parseColor("#3399ff");
private float textSize = getResources().getDimension(
R.dimen.alphabet_text_size);
public AlphabetView(Context context) {
super(context);
init(context);
}
public AlphabetView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public AlphabetView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context);
}
private void init(Context context) {
bitmap = BitmapFactory.decodeResource(getResources(),
R.drawable.alphabet_search_icon);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
final int height = getHeight();
final int width = getWidth();
int singleHeight = height / alphabetList.length;
final int size = alphabetList.length;
for (int i = 0; i < size; i++) {
if (alphabetList[i].equals("#")) {
if (isShowSearchIcon) {
float xPos = width / 2 - bitmap.getWidth() / 2;
float yPos = bitmap.getHeight() / 2;
// if(i == choose) {// 设置搜索icon选中效果
// final Bitmap b =
// BitmapFactory.decodeResource(getResources(),
// R.drawable.icon);
// canvas.drawBitmap(b, xPos, yPos, paint);
// } else {
canvas.drawBitmap(bitmap, xPos, yPos, paint);
// }
paint.reset();
}
} else {
paint.setColor(mDefaultColor);
paint.setAntiAlias(true);
paint.setTextSize(textSize);
if (i == choose) {
paint.setColor(mSelectColor);
paint.setFakeBoldText(true);
}
float xPos = width / 2 - paint.measureText(alphabetList[i]) / 2;
float yPos = singleHeight * i + singleHeight;
;
canvas.drawText(alphabetList[i], xPos, yPos, paint);
paint.reset();
}
}
}
/**
* 设置字母列表默认颜色
*
* @param color
*/
protected void setDefaultColor(int color) {
mDefaultColor = color;
}
/**
* 设置字母列表选中颜色
*
* @param color
*/
protected void setSelectColor(int color) {
mSelectColor = color;
}
/**
* 设置字体大小
*
* @param size
*/
protected void setTextSize(float size) {
textSize = size;
}
/**
* 设置搜索icon
*
* @param resid
*/
protected void setSearchIcon(int resid) {
bitmap = BitmapFactory.decodeResource(getResources(), resid);
}
/**
* 设置搜索icon
*
* @param resid
*/
protected void setSearchIcon(Drawable drawable) {
bitmap = ((BitmapDrawable) drawable).getBitmap();
}
/**
* 设置是否显示搜索icon
*
* @param isShowSearchIcon
*/
public void setShowSearchIcon(boolean isShowSearchIcon) {
this.isShowSearchIcon = isShowSearchIcon;
}
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
final int action = event.getAction();
final float y = event.getY();
final int oldChoose = choose;
final OnTouchingLetterChangedListener listener = onTouchingLetterChangedListener;
final int c = (int) (y / getHeight() * alphabetList.length);
switch (action) {
case MotionEvent.ACTION_DOWN:
if (oldChoose != c && listener != null) {
if (c >= 0 && c < alphabetList.length) {
if (alphabetList[c].equals("#")) {
if (isShowSearchIcon) {
listener.onTouchingLetterChanged("搜");
}
} else {
listener.onTouchingLetterChanged(alphabetList[c]);
}
choose = c;
setBackgroundResource(R.drawable.alphabet_list_bg);
invalidate();
}
}
break;
case MotionEvent.ACTION_MOVE:
if (oldChoose != c && listener != null) {
if (c >= 0 && c < alphabetList.length) {
if (alphabetList[c].equals("#")) {
if (isShowSearchIcon) {
listener.onTouchingLetterChanged("搜");
}
} else {
listener.onTouchingLetterChanged(alphabetList[c]);
}
choose = c;
invalidate();
}
}
break;
case MotionEvent.ACTION_UP:
choose = -1;
setBackgroundDrawable(null);
invalidate();
break;
}
return true;
}
public void setOnTouchingLetterChangedListener(
OnTouchingLetterChangedListener onTouchingLetterChangedListener) {
this.onTouchingLetterChangedListener = onTouchingLetterChangedListener;
}
public interface OnTouchingLetterChangedListener {
public void onTouchingLetterChanged(String s);
}
}
写道
Utils 的实现
package com.xiawenquan.test.utils;
import java.util.regex.Pattern;
public class Utils {
/***
*获得汉语拼音首字母
*不是字母返回#
*是字母返回字母
* */
public static 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 "#";
}
}
}
写道
ConteactMode 的实现
package com.xiawenquan.test.mode;
/**
* 封装数据的实体
* @author xiawenquan
*/
public class ConteactMode {
private String name;
private String id;
private String firstAlpha;
private String phone;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getFirstAlpha() {
return firstAlpha;
}
public void setFirstAlpha(String firstAlpha) {
this.firstAlpha = firstAlpha;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
}
package com.xiawenquan.test.adapter;
import java.util.ArrayList;
import com.xiawenquan.test.asyncqueryhandler.R;
import com.xiawenquan.test.mode.ConteactMode;
import android.content.Context;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
public class
写道
ContactAdapter 的实现
extends BaseAdapter {
private Context context;
private ArrayList<ConteactMode> modes;
public ContactAdapter(Context context){
this.context = context;
}
public void setData(ArrayList<ConteactMode> modes){
this.modes = modes;
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return modes != null && modes.size() > 0 ? modes.size() : 0;
}
@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return modes != null && modes.size() > 0 ? modes.get(position) : null;
}
@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
ViewHolder holder ;
if(convertView == null){
holder = new ViewHolder();
convertView = LayoutInflater.from(context).inflate(R.layout.alphalistview_item, null);
holder.fistAlphaTextView = (TextView) convertView.findViewById(R.id.first_alpha);
holder.nameTextView = (TextView) convertView.findViewById(R.id.name);
holder.phoneTextView = (TextView) convertView.findViewById(R.id.phone);
convertView.setTag(holder);
}else{
holder = (ViewHolder) convertView.getTag();
}
if(modes != null && modes.size() > 0){
ConteactMode conteactMode = modes.get(position);
if(conteactMode != null){
//名称
String name = conteactMode.getName();
if(!TextUtils.isEmpty(name)){
holder.nameTextView.setText(name);
}
//电话
String phone = conteactMode.getPhone();
if(!TextUtils.isEmpty(name)){
holder.phoneTextView.setText(phone);
}
//首字母(前后两项对比字母是否相同,如果相同则过滤,否则添加进来)
String currentAlpha = conteactMode.getFirstAlpha();
ConteactMode mode = (position - 1) >= 0 ? modes.get(position - 1) : null;
String previewStr = "";
if(mode != null){
previewStr = mode.getFirstAlpha();
}
if (!previewStr.equals(currentAlpha)) {
holder.fistAlphaTextView.setVisibility(View.VISIBLE);
holder.fistAlphaTextView.setText(currentAlpha);
}else{
holder.fistAlphaTextView.setVisibility(View.GONE);
}
}
}
return convertView;
}
class ViewHolder{
TextView fistAlphaTextView;
TextView nameTextView;
TextView phoneTextView;
}
}
写道
MainActivity 的实现
package com.xiawenquan.test.asyncqueryhandler;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.regex.Pattern;
import com.xiawenquan.test.adapter.ContactAdapter;
import com.xiawenquan.test.mode.ConteactMode;
import com.xiawenquan.test.utils.Utils;
import com.xiawenquan.test.widget.AlphabetListView;
import android.app.Activity;
import android.content.AsyncQueryHandler;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.Window;
import android.widget.CursorAdapter;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;
/**
* 简单使用AsyncQueryHandler
* @author xianweuqan
*
*/
@SuppressWarnings("unused")
public class MainActivity extends Activity {
private ArrayList<ConteactMode> modes;
protected QueryHandler mQueryHandler;
protected Cursor mCursor = null;
private AlphabetListView listView;
private HashMap<String, Integer> alphaIndexer ;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//定义要查询的数据
Uri uri = Uri.parse("content://com.android.contacts/data/phones");
getWindow().requestFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
setContentView(R.layout.activity_main);
modes = new ArrayList<ConteactMode>();
listView = (AlphabetListView) findViewById(R.id.mylistview);
//在这里加上加载框
mQueryHandler = new QueryHandler(getContentResolver());
query(uri);
}
/**
* 查询数据
* @param uri 数据的路径
*/
private void query(Uri uri) {
String[] projection = { "_id", "display_name", "data1", "sort_key" };
mQueryHandler.startQuery(0, null, uri, projection, null, null,
"sort_key COLLATE LOCALIZED asc");//按字母排序
}
@Override
protected void onStop() {
super.onStop();
if (mCursor != null) {
mCursor.deactivate();
}
}
class QueryHandler extends AsyncQueryHandler {
public QueryHandler(ContentResolver cr) {
super(cr);
}
@Override//查询完成后调用此方法
protected void onQueryComplete(int token, Object cookie, Cursor cursor) {
super.onQueryComplete(token, cookie, cursor);
setData(cursor);
//在这里取消加载框
}
}
/**
* 绑定数据
* @param cursor 游标
*/
private void setData(Cursor cursor){
if(cursor != null && cursor.getCount() > 0){
if(alphaIndexer == null){
alphaIndexer = new HashMap<String, Integer>();
cursor.moveToFirst();
for (int i = 0; i < cursor.getCount(); i++) {
cursor.moveToPosition(i);
//取出每一条数据
String name = cursor.getString(1);
String phone = cursor.getString(2);
String sortKey = cursor.getString(3);
//过滤"+86"
if(phone.startsWith("+86")){
phone = phone.substring(3);
}
//把数据封装在实体中
ConteactMode mode = new ConteactMode();
mode.setName(name);
mode.setPhone(phone);
String firstAlpha = Utils.getAlpha(sortKey);
mode.setFirstAlpha(firstAlpha);
//将封装的实体加到数组中
modes.add(mode);
}
for(int i = 0 ; i < modes.size() ; i++){
//处理当点击某一个字母后,其内容出现在屏幕可见状态下的最上面
ConteactMode conteactMode = modes.get(i);
String currentAlpha = conteactMode.getFirstAlpha();
ConteactMode mode = (i - 1) >= 0 ? modes.get(i - 1) : null;
String previewStr = "";
if(mode != null){
previewStr = mode.getFirstAlpha();
}
if (!previewStr.equals(currentAlpha)) {
alphaIndexer.put(currentAlpha,i);
}
}
//把数据设置到adapter
ContactAdapter adapter = new ContactAdapter(getApplicationContext());
adapter.setData(modes);
listView.setAlphabetIndex(alphaIndexer);
listView.setAdapter(adapter);
}
}
}
}
写道
最后附有源码,通过学习。