《Android进阶之光》--View体系与自定义View

No1:

View的滑动

1)layout()方法的

public class CustomView extends View{
    private int lastX;
    private int lastY;
    public CustomView(Context context,AttributeSet attrs,int defStyleAttr){
        super(context,attrs,defStyleAttr);
    }
    public CustomView(Context context,AttributeSet attrs){
        super(context,attrs);
    }
    public CustomView(Context context){
        super(context);
    }
    
    public boolean onTouchEvent(MotionEvent event){
        //获取手指摸点的横坐标和纵坐标
        int x = (int)event.getX();
        int y = (int)event.getY();
        
        switch(event.getAction()){
            case MotionEvent.ACTION_DOWN:
                lastX = x;
                lastY = y;
                break;
            case MotionEvent.ACTION_MOVE:
                //计算移动的距离
                int offsetX = x - lastX;
                int offsetY = y - lastY;
                //调用layout方法来重新放置它的位置
                layout(getLeft()+offsetX,getTop()+offsetY,getRight()+offsetX,getBottom()+offsetY);
                break;
        }
        return true;
    }
}

2)offsetLeftAndRight()与offsetTopAndBottom()

对上面代码进行修改

case MotionEvent.ACTION_MOVE:
    //计算移动的距离
    int offsetX = x - lastX;
    int offsetY = y - lastY;
    //对left和right进行偏移
    offsetLeftAndRight(offsetX);
    //对top和bottom进行偏移
    offsetTopAndBottom(offsetY);
    break;

3)LayoutParams(改变布局参数)

同样对上面代码进行修改

case MotionEvent.ACTION_MOVE:
    ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams)getLayoutParams();
    layoutParams.leftMargin = getLeft() + offsetX;
    layoutParams.topMargin = getTop() + offsetY;
    setLayoutParams(layoutParams);
    break;

4)动画

5)scrollTo与scrollBy

scrollTo(x,y)表示移动到一个具体的坐标点,而scrollBy(x,y)表示移动的增量为dx、dy。其中scrollBy最终也是要调用scrollTo的。

View.java的scrollBy和scrollTo源码

public void scrollTo(int x,int y){
    if(mScrollX!=x || mScrollY!=y){
        int oldX = mScrollX;
        int oldY = mScrollY;
        mScrollX = x;
        mScrollY = y;
        invalidateParentCaches();
        onScrollChanged(mScrollX,mScrollY,oldX,oldY);
        if(!awakenScrollBars()){
            postInvalidateOnAnimation();
        }
    }
}

public void scrollBy(int x,int y){
    scrollTo(mScrollX+x,mScrollY+y);
}

6)Scroller

public CustomView(Context context,AttributeSet attrs){
    super(context,attrs);
    mScroller = new Scroller(context);
}

@Override
public void computeScroll(){
    super.computeScroll();
    if(mScroller.computeScrollOffset()){
        ((View)getParent()).scrollTo(mScroller.getCurrX(),mScroller.getCurrY());
        invalidate();
    }
}

public void smoothScrollTo(int destX,int destY){
    int scrollX = getScrollX();
    int delta = destX-scrollX;
    mScroller.startScroll(scrollX,0,delta,0,2000);
    invalidate();
}

//最后调用
mCustomView.smoothScrollTo(-400,0);

No2:

View的measure流程,ViewGroup中定义了measureChildren方法

View和ViewGroup中均没有实现onLayout方法

No3:

View的draw流程

1)绘制背景:View.drawBackground()

2)绘制View的内容:重写View.onDraw()

3)绘制子View:ViewGroup.dispatchDraw()对子View进行遍历->ViewGroup.drawChild()->View.draw()

4)绘制装饰:View.onDrawForeground()

No4:

自定义View

1)继承系统控件的自定义View:重写onDraw()

2)继承View的自定义View:重写onDraw()、考虑warp_content属性以及padding属性设置、或者自定义属性、考虑是否重写onTouchEvent()

3)自定义组合控件

4)自定义ViewGroup:重写onLayout()、处理warp_content属性、处理滑动冲突、弹性滑动到其他页面、快速滑动到其他页面、再次触摸屏幕阻止页面继续滑动

相关推荐