zoukankan      html  css  js  c++  java
  • 《android开发艺术探索》读书笔记(三)--分发机制和滑动冲突

    接上篇《android开发艺术探索》读书笔记(二)

    No1:

    通过MotionEvent对象可以得到点击事件发生的x和y坐标,getX/getY返回的是相对于当前View左上角的x和y坐标,而getRawX/getRawY返回的是相对于手机屏幕左上角的x和y坐标。

    No2:

    TouchSlop是系统所能识别的被认为是滑动的最小距离,这是一个常量,和设备有关,在不同设备上这个值可能是不同的,通过如下的方式可以获取这个常量

    ViewConfiguration.get(getContext()).getScaledTouchSlop();

    No3:

    VelocityTracker -速度追踪

    首先在View的onTouchEvent方法中追踪

    VelocityTracker velocityTracker = VelocityTracker.obtain();
    velocityTracker.addMovement(event);

    采用如下方式来获取当前的速度

    velocityTracker.computeCurrentVelocity(1000);
    int xVelocity = (int)velocityTracker.getXVelocity();
    int yVelocity = (int)velocityTracker.getYVelocity();

    这里是指1000ms内手指在水平和竖直方向上滑过的像素

    速度=(终点位置-起点位置)/时间段

    重置并回收内存

    velocityTracker.clear();
    velocityTracker.recycle();

    No4:

    GestureDetector -手势检测

    首先需要创建一个GestureDetector对象并实现OnGestrueListener接口

    GestureDetector mGestureDetector = new GestureDetector(this);
    //解决长按屏幕后无法拖动的现象
    mGestureDetector.setIsLongpressEnabled(false);

    接着,在待监听View的onTouchEvent方法中添加如下实现

    boolean consume = mGestureDetector.onTouchEvent(event);
    return consume;

    No5:

     

    No6:

    如果只是监听滑动相关的,建议自己在onTouchEvent中实现

    如果要监听双击这种行为的话,那么就使用GestureDector

    No7:

    View的scrollTo/scrollBy的滑动过程是瞬间完成的。

    Scroller可以实现有过渡效果的滑动,Scroller本身无法让View弹性滑动,它需要和View的computeScroll方法配合才能实现。

    Scroller scroller = new Scroller(mContext);
    
    //缓慢滚动到指定位置
    private void smoothScrollTo(int destX,int dextY){
         int scrollX = getScrollX;
         int delta = destX - scrollX;
         //1000ms内滑动destX,效果就是慢慢滑动
         mScroller.startScroll(scrollX,0,delta,0,1000);
         invalidate();
    }
    
    @Override
    public void computeScroll(){
        if(mScroller.computeScrollOffset()){
              scrollTo(mScroller.getCurrX(),mScroller.getCurrY);
              postInvalidate();
        }
    }

    No8:

    View的滑动有三种实现方式

    1.通过View本身提供的scrollTo/scrollBy实现滑动

    2.通过动画给View施加平移效果来实现滑动

    3.通过改变View的LayoutParams使得View重新布局从而实现滑动

    No9:

    scrollBy实际上也是调用了scrollTo方法,它实现了基于当前位置的相对滑动,而scrollTo则实现了基于所传递参数的绝对滑动

    scrollTo和scrollBy只能将View的内容进行移动,并不能将View本身进行移动。例如:TextView移动的是TextView中的文字,而不是TextView本身

    No10:

    View的三种滑动方式比较

    scrollTo/scrollBy:操作简单,适合对View内容的滑动

    动画:操作简单,主要适用于没有交互的View和实现复杂的动画效果

    改变布局参数:操作稍微复杂,适用于有交互的View

    No11:

    View跟手滑动效果

    public boolean onTouchEvent(MotionEvent event){
        int x = (int)event.getRawX();
        int y = (int)event.getRawY();
        switch(event.getAction()){
            case MotionEvent.ACTION_DOWN:
                break;
            case MotionEvent.ACTION_MOVE:
                int deltaX = x - mLastX;
                int deltaY = y - mLastY;
                int translationX = (int)ViewHelper.getTranslationX(this) + deltaX;
                int translationY = (int)ViewHelper.getTranslationY(this) + deltaY;
                ViewHelper.setTranslationX(this,translationX);
                ViewHelper.setTranslationY(this,translationY);
                break;
            case MotionEvent.ACTION_UP;
                break;
            default:
                break;    
        }
        
        mLastX = x;
        mLastY = y;
        return true;
    }

    No12:

    Scroller滑动原理:当View重绘后会在draw方法中调用computeScroll,而computeScroll又会去向Scroller获取当前的scrollX和scrollY;然后通过scrollTo方法实现滑动;接着又调用postInvalidata方法来进行第二次重绘,这一次重绘的过程和第一次重绘一样,还是会导致computeScroll方法被调用;然后继续向Scroller获取scrollX和scrollY,并通过scrollTo方法滑动到新的位置,如此反复,知道整个滑动过程结束。

    其中,computeScroll的作用就是计算当前View的滑动位置

    No13:

    ViewGroup默认不拦截任何事件,Android源码中ViewGroup的onInterceptTouchEvent方法默认返回false,

    View没有onInterceptTouchEvent方法,一旦有点击事件传递给它,那么它的onTouchEvent方法就会被调用。

    View的onTouchEvent默认都会消耗事件(返回true),除非它是不可点击的(clickable和longClickable同时为false)。

    No14:

    Window的实现类是PhoneWindow

    No15:

    如何根据坐标来得到滑动的方向呢?

    1.可以依据滑动路径水平方向所形成的夹角

    2.依据水平方向和竖直方向上的距离差来判断

    3.依据水平竖直方向的速度差来做判断

    No16:

    外部拦截法需要重写父容器的onInterceptTouchEvent方法,在内部做相应的拦截即可

    public boolean onInterceptTouchEvent(MotionEvent event){
        boolean intercepted = false;
        int x = (int)event.getX();
        int y = (int)event.getY();
        switch(event.getAction()){
            case MotionEvent.ACTION_DOWN:{
                intercepted = false;
            }
            case MotionEvent.ACTION_MOVE:{
                if(父容器需要当前点击事件){
                    intercepted = true;
                }else{
                    intercepted = false;
                }
                break;
            }
            case MotionEvent.ACTION_UP:{
                intercepted = false;
                break;
            }
            default:
                break;
        }
        mLastXIntercept = x;
        mLastYIntercept = y;
        return intercepted;
    }

    内部拦截法需要配合requestDisallowInterceptTouchEvent,需要重写子元素的dispatchTouchEvent方法

    public boolean dispatchTouchEvent(MotionEvent event){
        int x = (int)event.getX();
        int y = (int)event.getY();
        switch(event.getAction()){
            case MotionEvent.ACTION_DOWN:{
                parent.requestDisallowInterceptTouchEvent(true);
                break;
            }
            case MotionEvent.ACTION_MOVE:{
                int deltaX = x - mLastX;
                int deltaY = y - mLastY;
                if(父容器需要当前点击事件){
                    parent.requestDisallowInterceptTouchEvent(false);
                }
                break;
            }
            case MotionEvent.ACTION_UP:{
                break;
            }
            default:
                break;
        }
        mLastX = x;
        mLastY = y;
        return super.dispatchTouchEvent(event);
    }

    推荐外部拦截法

  • 相关阅读:
    算法笔记--中国剩余定理
    算法笔记--辛普森积分公式
    算法笔记--数学之不定方程解的个数
    算法笔记--卢卡斯定理
    洛谷 P3808 【模板】AC自动机(简单版)洛谷 P3796 【模板】AC自动机(加强版)
    hihocoder #1419 : 后缀数组四·重复旋律4
    codevs 3044 矩形面积求并 || hdu 1542
    Stamps ans Envelope Sive UVA
    洛谷 P2061 [USACO07OPEN]城市的地平线City Horizon
    bzoj 3277: 串
  • 原文地址:https://www.cnblogs.com/anni-qianqian/p/7251742.html
Copyright © 2011-2022 走看看