今天给大家带来一个我们常见的导航
是不是很常见有木有??
其实这个自定义view很简单,我带大家一起来研究研究
1.首先得有个数据源,数据源就是你要展示在右边的数据
private String[] strs = { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M",
"N", "P", "Q", "R", "S", "T", "W", "X", "Y", "Z"};
2.初始化画笔,这里定义了两个画笔,一个是普通的画笔,一个是手指触摸的画笔
paintTxt = new Paint();
paintTxt.setColor(Color.parseColor("#1BB6D1"));
paintTxt.setTextSize(50);
paintTxt.setAntiAlias(true);
paintChecked = new Paint();
paintChecked.setColor(Color.parseColor("#606776"));
paintChecked.setTextSize(50);
paintChecked.setAntiAlias(true);
3.onMeasure测量,一个View要显示在视图上,首先要经过onMeasure方法测量得到该view的大小,然后通过Onlayout确定它本身在摆放的位置,最后
才是ondraw进行绘制。
private int measureSpec(int spec,int type){
int rsize = 0;
int mode = MeasureSpec.getMode(spec);
int size = MeasureSpec.getSize(spec);
switch (mode) {
case MeasureSpec.EXACTLY:
rsize = size;
break;
case MeasureSpec.AT_MOST:
if(type == 0){ //测量宽度
rsize = (int) (paintTxt.measureText(strs[0])+getPaddingLeft()+getPaddingRight());
}else{ //测量高度
rsize = size;
}
break;
case MeasureSpec.UNSPECIFIED:
break;
default:
break;
}
return rsize;
}
如果是Mode是EXACTLY,说明是确定大小的,就直接让系统测出来的size去赋值就行,如果Mode是AT_MOST的话,就说明view是根据自身内容大小决定的,宽度就是字体的宽度加上左右Padding得到。
3.进行绘制,如果是被选中的,就用另外一只画笔绘制
protected void onDraw(Canvas canvas) {
int width = getWidth();
int height = getHeight();
conentHeigt = height/strs.length;
for (int i = 0; i < strs.length; i++) {
if(i == checked){
canvas.drawText(strs[i], width/2-paintTxt.measureText(strs[i])/2,conentHeigt*(1+i),paintChecked);
}else{
canvas.drawText(strs[i], width/2-paintTxt.measureText(strs[i])/2,conentHeigt*(1+i),paintTxt);
}
}
}
4.在onTouchEvent方法中进行触摸判断
@Override
public boolean onTouchEvent(MotionEvent event) {
int y = (int) event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
measureIndex(y);
break;
case MotionEvent.ACTION_MOVE:
measureIndex(y);
break;
case MotionEvent.ACTION_UP:
this.checked = -1;
invalidate();
break;
}
return true;
}
measureIndex方法是判断当前手指触摸的位置是对应整个导航的哪一个数值
private void measureIndex(int y){
int checked = y/conentHeigt;
if(checked == this.checked){
return;
}
if(checked < 0){
checked = 0;
}
if(checked >= strs.length){
checked = strs.length - 1;
}
this.checked = checked;
if(onCheckedCallBack != null){
onCheckedCallBack.onChecked(strs[this.checked]);
}
invalidate();
}
这里利用接口回调弄一个接口调用当前坐标所对应的数值暴露出去。
public interface OnCheckedCallBack{
void onChecked(String checkedStr);
}
public void setOnCheckedCallBack(OnCheckedCallBack onCheckedCallBack) {
this.onCheckedCallBack = onCheckedCallBack;
}
这样大体就实现的一个自定义SIdeBar