美文网首页
Android 群英传-第五章:Android Scroll 分

Android 群英传-第五章:Android Scroll 分

作者: Reiser实验室 | 来源:发表于2017-06-19 23:49 被阅读21次

    概念

    滑动是如何产生的

    滑动一个VIew,本质上是移动一个View。移动一个View需要改变他的坐标,所以滑动一个View分为两步:

    1. 监听用户的触摸事件,并获得事件的坐标。
    2. 根据事件坐标动态且不断的改变View的坐标。

    坐标系

    1. Android坐标系,以屏幕为坐标原点,Y轴向下,X轴向右增大可以通过getLocationOnScreen(int location[])来获取。触控事件中使用getRawX()getRawY()来获取
    2. 视图坐标系,以父视图的左上角为坐标原点。在触控事件中,通过getX(),getY()来获取

    触控事件

    触控事件MothinEvent,它封装了一些常量

    //单点触摸按下动作
    public static final int ACTION_DOWN = 0;
    //单点触摸离开动作
    public static final int ACTION_UP= 1; 
    //触摸点移动操作
    public static final int ACTION_MOVE = 2;
    //触摸动作取消
    public static final int ACTION_CANCEL= 3;
    //触摸动作超出边界
    public static final int ACTION_OUTSIDE = 4;
    //多点触控按下操作
     public static final int ACTION_PIOINTER_MOVE = 5;
     //多点离开动作
     public static final int ACTION_PIOINTER_UP= 6;
    

    在代码中

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        //视图坐标
        int x = (int) event.getX();
        int y = (int) event.getY();
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                //处理按下操作
                break;
            case MotionEvent.ACTION_MOVE:
                //处理移动事件
                break;
            case MotionEvent.ACTION_UP:
                //处理输入离开事件
                break;
        }
        return true;
    }
    

    获取坐标的方法:

    1. VIew提供的方法:getTop(),getLeft(),getRight(),getBottom.分别获取View自身到父布局上左右下的距离
    2. MotionEvent提供的方法:视图坐标getX(),getY();绝对坐标getRawX(),getRawY()(使用绝对坐标时,需要保存上次的坐标)

    滑动的七种方式

    在自定义view中处理onTouchEvent事件,通过获取到手指移动的距离.启动方式都是通过移动的距离来移动view的。

    方式一:layout方法

    方式二:offsetLeftAndRight(),offsetTopAndBottom()

    方式三:layoutParams

    方式四:scrollTo与scrollBy

    scrollTo是移动到一个具体的坐标点,scrollBy是移动一段距离。
    使用scrollTo与scrollBy移动的是content,所以需要getParent(),且因为坐标的参考系的变化,移动的值需要为相反数。

    @Override
    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;
                //方式一:layou
                layout(getLeft() + offsetX, getTop() + offsetY, getRight() + offsetX, getBottom() + offsetY);
                //方式二:offsetLeftAndRight
                offsetLeftAndRight(offsetX);
                offsetTopAndBottom(offsetY);
                //方式三:LayoutParams
                ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) getLayoutParams();
                layoutParams.leftMargin = getLeft() + offsetX;
                layoutParams.topMargin = getTop() + offsetY;
                setLayoutParams(layoutParams);
                //方式四scrollBy
                ((View)getParent()).scrollBy(-offsetX,-offsetY);
                break;
            case MotionEvent.ACTION_UP:
    
                break;
        }
    

    方式五:Scroller

    Scroller是一个辅助类,只是不断的改变值。本质还是使用scrollTo与scrollBy来移动VIew,方法有:

     public void startScroll(int startX,int startY,int dx, int dy,int duration)
     public void startScroll(int startX,int startY,int dx, int dy)
    

    使用步骤:

    • 初始化Scroller
    • 重写computeScroll(),实现模拟滑动
    • startScroll开启模拟过程

    computeScroll不会主动调用,只能通过invalidate()->draw()-> computeScroll()

    方式六:属性动画

    方式七: ViewDragHelper

    public class DragViewGroup extends FrameLayout {
        private ViewDragHelper mViewDragHelper;
        private View mMenuView, mMainView;
        private int mWidth;
    
        public DragViewGroup(@NonNull Context context) {
            super(context);
            initView();
        }
    
        public DragViewGroup(@NonNull Context context, @Nullable AttributeSet attrs) {
            super(context, attrs);
            initView();
        }
    
        public DragViewGroup(@NonNull Context context, @Nullable AttributeSet attrs, @AttrRes 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) {
            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) {
                return mMainView == child;
            }
    
            @Override
            public int clampViewPositionHorizontal(View child, int left, int dx) {
                return left;
            }
    
            @Override
            public int clampViewPositionVertical(View child, int top, int dy) {
                return 0;
            }
    
            @Override
            public void onViewReleased(View releasedChild, float xvel, float yvel) {
                super.onViewReleased(releasedChild, xvel, yvel);
                if (mMainView.getLeft() < 500) {
                    mViewDragHelper.smoothSlideViewTo(mMainView, 0, 0);
                    ViewCompat.postInvalidateOnAnimation(DragViewGroup.this);
                } else {
                    mViewDragHelper.smoothSlideViewTo(mMainView, 300, 0);
                    ViewCompat.postInvalidateOnAnimation(DragViewGroup.this);
                }
            }
        };
        @Override
        public void computeScroll() {
            super.computeScroll();
            if (mViewDragHelper.continueSettling(true)) {
                ViewCompat.postInvalidateOnAnimation(this);
            }
        }
    }
    

    相关文章

      网友评论

          本文标题:Android 群英传-第五章:Android Scroll 分

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