文章出處
文章列表
自定義控件的三個方法
- onMeasure() 測量控件的寬和高
- onLayout() 擺放控件的位置
- 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()測量的時候,得到的值與你在布局文件中寫的是有偏差的。
文章列表
全站熱搜