欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

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

程序员文章站 2022-04-14 13:01:55
No1: View的滑动 1)layout()方法的 2)offsetLeftAndRight()与offsetTopAndBottom() 对上面代码进行修改 3)LayoutParams(改变布局参数) 同样对上面代码进行修改 4)动画 5)scrollTo与scrollBy scrollTo( ......

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属性、处理滑动冲突、弹性滑动到其他页面、快速滑动到其他页面、再次触摸屏幕阻止页面继续滑动