自定义侧滑面板(SlieMenu)控件详解

自定义控件的三个方法

  1. onMeasure() 测量控件的宽和高
  2. onLayout() 摆放控件的位置
  3. onDraw() 绘制布局

下面看一点下代码:

public class SlideMenu extends ViewGroup {

private float downX;
private float moveX;
private Scroller scroller;

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

public SlideMenu(Context context, AttributeSet attrs) {
this(context, null,0);
}

public SlideMenu(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}

private void init() {
scroller = new Scroller(getContext());
}

/**
* 设置子View的宽高
* @param widthMeasureSpec 当前控件的宽度(测量规则)
* @param heightMeasureSpec 当前控件的高度(测量规则)
/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
/

leftMenu的宽是指定的450dp,高是matchparent
*/
//指定SlideMenu的宽高
View leftMenu = getChildAt(0);
//宽是子空间指定的宽,高直接是父控件的高
Log.i(getClass().getSimpleName(),"width : "+leftMenu.getMeasuredWidth());
leftMenu.measure(leftMenu.getLayoutParams().width,heightMeasureSpec);

/*
mainContent的宽和高都是match_parent
*/
//指定content的宽高
View mainContent = getChildAt(1);
mainContent.measure(widthMeasureSpec,heightMeasureSpec);

super.onMeasure(widthMeasureSpec,heightMeasureSpec);

}

/**
* 摆放控件的位置
* @param changed 当前控件的尺寸大小和位置是否发生了改变
* @param l left 当前控件的右边距
* @param t top 当前控件的顶边距
* @param r right 当前控件的右边界
* @param b bottom当前控件的下边界
/
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
/

摆放leftMenu的位置,
*/
View leftMenu = getChildAt(0);
leftMenu.layout(-leftMenu.getMeasuredWidth(),0,0,b);

/*
摆放mainContent的位置
*/
getChildAt(1).layout(l,t,r,b);

}

@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()){
case MotionEvent.ACTION_DOWN://按下
downX = event.getX();//获取按下时的X的坐标
break;
case MotionEvent.ACTION_MOVE://滑动
moveX = event.getX();//获取滑动时的X的坐标

//将要滑动的距离
int scroll = (int) (downX - moveX);//这里是一个负值

//计算将要滚动到的位置,判断是否会超出去 getScroll()右边界相对于当前View X轴的变异量,是个带正负号的值。
int newScroll = getScrollX() + scroll;

/*
scrollTo()滚动到指定的位置
scrollBy()在原来的基础上滚动
*/
//如果将要滑动的距离超过了leftMenu的宽,就直接指定X坐标的位置,将leftMenu显示出来
if (newScroll < -getChildAt(0).getMeasuredWidth()){
scrollTo(-getChildAt(0).getMeasuredWidth(),0);
}else if (newScroll>0){//如果向左滑的话,
scrollTo(0,0);
} else{
scrollBy(scroll,0);
}
downX = moveX;//必须要将moveX赋值给downX,因为滑动的过程是一小段一小段的滑动
break;
case MotionEvent.ACTION_UP://拿起

Log.i(getClass().getSimpleName(),"getScrollX: "+getScrollX());
if (getScrollX() <= -(getChildAt(0).getMeasuredWidth())/2.0f){//当leftMenu画出来显示了一半的时候
scrollTo(-getChildAt(0).getMeasuredWidth(),0);
}else {//当没有滑出一半的时候
scrollTo(0,0);
}
break;
default:
break;
}
return true;//消费事件
}

@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
}
}

注意

onMeasure()测量的时候,得到的值与你在布局文件中写的是有偏差的。

posted @ 2017-03-14 14:08  Godfunc  阅读(380)  评论(0)    收藏  举报