文章出處

自定義控件的三個方法

  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()測量的時候,得到的值與你在布局文件中寫的是有偏差的。


文章列表




Avast logo

Avast 防毒軟體已檢查此封電子郵件的病毒。
www.avast.com


arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()