一,好友排序
好友排序是按照昵称拼音进行A-Z排序。效果如下图:
对好友昵称进行排序,需要先将首字转换为ASCII码,然后根据ASCII码得到对应的拼音,最后根据拼音进行A-Z排序。点击按压右边的字母栏,会同步更新列表显示,并且显示当前点击的字母。
代码实现:
1. ContactsModel:好友列表实体。其中,如果用户昵称为成龙,则sortLetter为C,sortPinyin为CHEN。
另外,photo(头像)属性由于是以String类型在客户端与服务器之间传输,而在客户端显示需要Drawable类型,所以photo要在String和Drawable之间转换。
public class ContactsModel{
/**昵称首汉字的拼音首字母。用于显示*/
private String sortLetter;
/**昵称首汉字的全拼音。用于排序*/
private String sortPinyin;
private String userId;
private String name;
private String gender;
private Drawable photo;
public Drawable getPhoto() {
return photo;
}
public void setPhoto(Drawable photo) {
this.photo = photo;
}
public void setPhoto(String photo) {
this.photo = ViewUtils.StringToDrawable(photo);
}
//...
}
String和Drawable转换类
public class ViewUtils {
/**
* 将照片存储为字符串形式(经过BASE64编码)
*/
public static String DrawableToString(Drawable drawable) {
if(drawable == null)
{
return "";
}
BitmapDrawable bd = (BitmapDrawable)drawable;
Bitmap bmp = bd.getBitmap();
if(bmp == null)
return "";
ByteArrayOutputStream stream = new ByteArrayOutputStream();
//压缩图片
bmp.compress(Bitmap.CompressFormat.PNG, 60, stream);
byte[] b = stream.toByteArray();
// Base64Coder编码,将图片流以字符串形式存储下来
return Base64Coder.encodeLines(b);
}
/**
* 将Base64Coder编码后的字符串转换为Drawable
*/
public static Drawable StringToDrawable(String encodeStr) {
if(encodeStr==null || encodeStr.isEmpty())
{
return null;
}
//Base64Coder解码
ByteArrayInputStream in = new ByteArrayInputStream(Base64Coder.decodeLines(encodeStr));
Bitmap dBitmap = BitmapFactory.decodeStream(in);
Drawable drawable = new BitmapDrawable(dBitmap);
return drawable;
}
}
2. SideBar:自定义View,右侧字母索引。setTextView用于设置显示字母的TextView,比如上图的S字母框(该TextView的显示和隐藏已在内部实现,无需调用者操作)。setOnTouchingLetterChangedListener用于设置按压字母的回调函数,在OnTouchingLetterChangedListener函数中处理相应操作,如更新ListView显示。
public class SideBar extends View {
/**触摸事件*/
private OnTouchingLetterChangedListener mOnTouchingLetterChangedListener;
/**26个字母*/
public static String[] mLetters = { "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 boolean mIsPress;
/**选中字母位置*/
private int mChoose = -1;
private Paint mPaint = new Paint();
private TextView mTextDialog;
public SideBar(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
setBackgroundDrawable(new ColorDrawable(0xFFFFFFFF));
}
public SideBar(Context context, AttributeSet attrs) {
super(context, attrs);
setBackgroundDrawable(new ColorDrawable(0xFFFFFFFF));
}
public SideBar(Context context) {
super(context);
setBackgroundDrawable(new ColorDrawable(0xFFFFFFFF));
}
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 获取焦点改变背景颜色.
int height = getHeight();// 获取对应高度
int width = getWidth(); // 获取对应宽度
int singleHeight = height / mLetters.length;// 获取每一个字母的高度
if(mIsPress)//处于按压态
{
for (int i = 0; i < mLetters.length; i++) {
//字体改为黑色粗体
mPaint.setColor(Color.parseColor("#000000"));
mPaint.setTypeface(Typeface.DEFAULT_BOLD);
mPaint.setAntiAlias(true);
mPaint.setTextSize(18);
// 选中的状态
if (i == mChoose) {
mPaint.setColor(Color.parseColor("#FFFFFF"));
mPaint.setFakeBoldText(true);
}
// x坐标等于中间-字符串宽度的一半.
float xPos = width / 2 - mPaint.measureText(mLetters[i]) / 2;
float yPos = singleHeight * i + singleHeight;
canvas.drawText(mLetters[i], xPos, yPos, mPaint);
mPaint.reset();// 重置画笔
}
}else//正常状态
{
for (int i = 0; i < mLetters.length; i++) {
mPaint.setColor(Color.parseColor("#E0E0E0"));
mPaint.setTypeface(Typeface.DEFAULT);
mPaint.setAntiAlias(true);
mPaint.setTextSize(16);
// x坐标等于中间-字符串宽度的一半.
float xPos = width / 2 - mPaint.measureText(mLetters[i]) / 2;
float yPos = singleHeight * i + singleHeight;
canvas.drawText(mLetters[i], xPos, yPos, mPaint);
mPaint.reset();// 重置画笔
}
}
}
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
final int action = event.getAction();
final float y = event.getY();// 点击y坐标
final int oldChoose = mChoose;
final OnTouchingLetterChangedListener listener = mOnTouchingLetterChangedListener;
// 点击y坐标所占总高度的比例*mLetters数组的长度就等于点击mLetters中的个数.
final int c = (int) (y / getHeight() * mLetters.length);
switch (action) {
case MotionEvent.ACTION_UP:
setBackgroundDrawable(new ColorDrawable(0xFFFFFFFF));