美文网首页程序员
Android群英传读书笔记(第五章)

Android群英传读书笔记(第五章)

作者: 青藤绿 | 来源:发表于2016-01-21 21:30 被阅读375次

    上一章

    书中的示例代码:github

    1.Android的坐标系是以左上角为顶点,向右为x轴正方向,向下是y轴正方向。在触控事件中通过getRawX()getRawY()获取Android坐标系中的坐标。在View中通过getLocationOnScreen(intlocation[])获取。

    2.视图坐标系描述的是子视图在父视图中的位置关系,原点为父视图的右上角,x、y轴方向与Android坐标系一致。触控事件中通过getX(),getY()获取。还可以通过getTop(),getLeft(),getBottom(),getRight()来获取到父视图的距离。

    3.MotionEvent常用事件常量:

    MotionEvent.ACTION_DOWN//单点触摸按下动作
    MotionEvent.ACTION_UP//单点触摸离开动作
    MotionEvent.ACTION_MOVE//触摸点移动动作
    MotionEvent.ACTION_CANCEL//触摸动作取消
    MotionEvent.ACTION_OUTSIDE//触摸动作超出边界
    MotionEvent.ACTION_POINTER_DOWN//多点触摸按下动作
    MotionEvent.ACTION_POINTER_UP//多点离开动作
    

    4.实现滑动的七种方法:

    • layout()方法:
    private int lastX;
        private int lastY;
        private int offsetX;
        private int offsetY;
    
        @Override
        public boolean onTouchEvent(MotionEvent event) {
            int x = (int) event.getRawX();
            int y = (int) event.getRawY();
    
            switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                lastX = x;
                lastY = y;
                break;
            case MotionEvent.ACTION_MOVE:
                offsetX = x - lastX;
                offsetY = y - lastY;
    
                layout(getLeft() + offsetX, getTop() + offsetY, getRight() + offsetX, getBottom() + offsetY);
    
                lastX = x;
                lastY = y;
                break;
            }
    
            return true;
        }
    
    • offsetLeftAndRight()offsetTopAndBottom()方法:
    //替换上面的layout方法即可
    offsetLeftAndRight(offsetX);
    offsetTopAndBottom(offsetY);
    
    • LayoutParams方法:
    //替换上面的layout方法即可
    ViewGroup.MarginLayoutParams layoutParams=(MarginLayoutParams) getLayoutParams();
                layoutParams.leftMargin=getLeft()+offsetX;
                layoutParams.topMargin=getTop()+offsetY;
                setLayoutParams(layoutParams);
    
    • scrollToscrollBy
        //scrollTo和scrollBy移动的是view的内容而不是view本身
        //如果在viewgroup中使用就是移动所有子view。
        View view=(View) getParent();
        //scrollTo和scrollBy参考的坐标系正好与视图坐标系相反,所以offset需为负
        view.scrollBy(-offsetX, -offsetY);
    
    • Scroller:
      使用Scroller主要有三个步骤:
      1.初始化Scroller对象,一般在view初始化的时候同时初始化scroller
      2.重写viewcomputeScroll方法,computeScroll方法是不会自动调用的,只能通过invalidate来间接调用,实现循环获取scrollXscrollY的目的,当移动过程结束之后,Scroller.computeScrollOffset方法会返回false,从而中断循环;
      3.调用Scroller.startScroll方法,将起始位置、偏移量以及移动时间(可选)作为参数传递给startScroll方法。
      这个例子中,要实现的是view跟着手指滑动 松手后平滑移动到原位置。
      先初始化Scroller
    mScroller=new Scroller(getContext());
    

    然后重写ViewcomputeScroll()方法

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

    最后在onTouchEventMotionEvent.ACTION_UP时开启移动

    @Override
        public boolean onTouchEvent(MotionEvent event) {
            int x = (int) event.getX();
            int y = (int) event.getY();
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    lastX = (int) event.getX();
                    lastY = (int) event.getY();
                    break;
                case MotionEvent.ACTION_MOVE:
                    int offsetX = x - lastX;
                    int offsetY = y - lastY;
                    ((View) getParent()).scrollBy(-offsetX, -offsetY);
                    break;
                case MotionEvent.ACTION_UP:
                    // 手指离开时,执行滑动过程
                    View viewGroup = ((View) getParent());
                    mScroller.startScroll( viewGroup.getScrollX(), viewGroup.getScrollY(),
                            -viewGroup.getScrollX(), -viewGroup.getScrollY(),1000);
                    invalidate();
                    break;
            }
            return true;
        }
    

    Scroller的实现原理就是不断调用scrollTo或者scrollBy

    • 属性动画(以后章节会详细介绍)
    • ViewDragHelper
      ViewDragHelper基本可以实现各种不同滑动需求,但使用稍微复杂。
    public class DragViewGroup extends FrameLayout {
    
        private ViewDragHelper mViewDragHelper;
        private View mMenuView, mMainView;
        private int mWidth;
    
        public DragViewGroup(Context context) {
            super(context);
            initView();
        }
    
        public DragViewGroup(Context context, AttributeSet attrs) {
            super(context, attrs);
            initView();
        }
    
        public DragViewGroup(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            initView();
        }
    
        @Override
        protected void onFinishInflate() {
            super.onFinishInflate();
            mMenuView = getChildAt(0);
            mMainView = getChildAt(1);
        }
    
        @Override
        protected void onSizeChanged(int w, int h, int oldw, int oldh) {
            super.onSizeChanged(w, h, oldw, oldh);
            mWidth = mMenuView.getMeasuredWidth();
        }
    
        @Override
        public boolean onInterceptTouchEvent(MotionEvent ev) {
            return mViewDragHelper.shouldInterceptTouchEvent(ev);
        }
    
        @Override
        public boolean onTouchEvent(MotionEvent event) {
            //将触摸事件传递给ViewDragHelper,此操作必不可少
            mViewDragHelper.processTouchEvent(event);
            return true;
        }
    
        private void initView() {
            mViewDragHelper = ViewDragHelper.create(this, callback);
        }
    
        private ViewDragHelper.Callback callback = new ViewDragHelper.Callback() {
    
                    // 何时开始检测触摸事件
                    @Override
                    public boolean tryCaptureView(View child, int pointerId) {
                        //如果当前触摸的child是mMainView时开始检测
                        return mMainView == child;
                    }
    
                    // 触摸到View后回调
                    @Override
                    public void onViewCaptured(View capturedChild, int activePointerId) {
                        super.onViewCaptured(capturedChild, activePointerId);
                    }
    
                    // 当拖拽状态改变,比如idle,dragging
                    @Override
                    public void onViewDragStateChanged(int state) {
                        super.onViewDragStateChanged(state);
                    }
    
                    // 当位置改变的时候调用,常用与滑动时更改scale等
                    @Override
                    public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {
                        super.onViewPositionChanged(changedView, left, top, dx, dy);
                    }
    
                    // 处理垂直滑动
                    @Override
                    public int clampViewPositionVertical(View child, int top, int dy) {
                        return 0;
                    }
    
                    // 处理水平滑动
                    @Override
                    public int clampViewPositionHorizontal(View child, int left, int dx) {
                        return left;
                    }
    
                    // 拖动结束后调用
                    @Override
                    public void onViewReleased(View releasedChild, float xvel, float yvel) {
                        super.onViewReleased(releasedChild, xvel, yvel);
                        //手指抬起后缓慢移动到指定位置
                        if (mMainView.getLeft() < 500) {
                            //关闭菜单,相当于Scroller的startScroll方法
                            mViewDragHelper.smoothSlideViewTo(mMainView, 0, 0);
                            ViewCompat.postInvalidateOnAnimation(DragViewGroup.this);
                        } else {
                            //打开菜单
                            mViewDragHelper.smoothSlideViewTo(mMainView, 300, 0);
                            ViewCompat.postInvalidateOnAnimation(DragViewGroup.this);
                        }
                    }
                };
    
        @Override
        public void computeScroll() {
            if (mViewDragHelper.continueSettling(true)) {
                ViewCompat.postInvalidateOnAnimation(this);
            }
        }
    }
    

    下一章

    相关文章

      网友评论

        本文标题:Android群英传读书笔记(第五章)

        本文链接:https://www.haomeiwen.com/subject/jpglkttx.html