您的位置:首页 > 移动开发 > Android开发

Android 通讯录(2)-----自定义View实现右侧导航栏

2017-07-03 17:32 295 查看

前言

前一篇介绍了怎么通过自定义ItemDecoration来实现通讯录的分类标题,那么本篇文章中,我们将继续通过自定义View来实现右侧导航栏。如果你还没有看过我的上一篇文章,可以先去阅读 Android 通讯录(1)—–自定义ItemDecoration实现分类标题

最终效果



实现

public class CustomIndexBar extends View {
public static String[] INDEX_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 int height, width;//view的宽高
private int indexHeight;//每个字的高度
private Paint mPaint;
private Rect mBounds;
private int bgColor;//背景颜色
private int textSize;//字体大小
private int touchPosition;
private List<String> mIndexDatas;

public CustomIndexBar(Context context) {
this(context, null);
}

public CustomIndexBar(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);//手动调用第3个构造函数
}

public CustomIndexBar(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
//取出自定义属性值以及其他一些初始化操作
init(context, attrs, defStyleAttr);
}

private void init(Context context, AttributeSet attrs, int defStyleAttr) {
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CustomIndexBar, defStyleAttr, 0);
for (int i = 0; i < typedArray.getIndexCount(); i++) {
int attr = typedArray.getIndex(i);
switch (attr) {
case R.styleable.CustomIndexBar_textSize:
textSize = typedArray.getDimensionPixelSize(attr, (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 16, context.getResources().getDisplayMetrics()));
break;
case R.styleable.CustomIndexBar_backgroundColor:
bgColor = typedArray.getColor(attr, Color.BLACK);
break;
}
}
typedArray.recycle();

mIndexDatas = Arrays.asList(INDEX_STRING);//数据源
mPaint = new Paint();
mPaint.setAntiAlias(true);
mBounds = new Rect();
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
width = getMeasuredWidth();
height = getMeasuredHeight() - getPaddingTop() - getPaddingBottom();
//获取每一个的高度
indexHeight = height / mIndexDatas.size();
}

@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
mPaint.setTextSize(textSize);
for (int i = 0; i < mIndexDatas.size(); i++) {
mPaint.getTextBounds(mIndexDatas.get(i), 0, mIndexDatas.get(i).length(), mBounds);
canvas.drawText(mIndexDatas.get(i), width / 2 - mBounds.width() / 2, getPaddingTop() + i * indexHeight + indexHeight - (indexHeight / 2 - mBounds.height() / 2), mPaint);
}
}

@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
//设置ACTION_DOWN时的背景颜色。
setBackgroundColor(bgColor);
//计算点击位置
touchPosition = (int) ((event.getY() - getPaddingTop())/indexHeight);
if(touchPosition <= 0){
touchPosition = 0;
}else {
if(touchPosition >= mIndexDatas.size() - 1){
touchPosition = mIndexDatas.size() - 1;
}
}
EventBus.getDefault().post(new MessageEvent(mIndexDatas.get(touchPosition)));
break;
case MotionEvent.ACTION_MOVE:
touchPosition = (int) ((event.getY() - getPaddingTop())/indexHeight);
if(touchPosition <= 0){
touchPosition = 0;
}else {
if(touchPosition >= mIndexDatas.size() - 1){
touchPosition = mIndexDatas.size() - 1;
}
}
EventBus.getDefault().post(new MessageEvent(mIndexDatas.get(touchPosition)));
break;
case MotionEvent.ACTION_UP:
setBackgroundResource(android.R.color.transparent);
EventBus.getDefault().post(new MessageEvent("up"));
break;
}
return true;
}
}


其中构造函数:

一个参数的构造函数:new新建的时候调用。

两个参数的构造函数:xml中引用CustomIndexBar时调用

三个参数的构造函数:通常是在两个参数的构造函数中通过this(context, attrs, 0); 来手动调用,以取出自定义属性的值。

完整demo

点我下载
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐