第三章View的事件体系(Android开发艺术探索)

    xiaoxiao2021-03-25  140

    阅读本章你将了解:

    1.MotionEvent(运动事件) 2.TouchSlop(触摸坡;最小滑动距离,每个手机大小不一) 3.VelocityTracker (速度追踪) 4.GestureDetector(手势检测器) 5.Scroller(弹性滑动)

    3.1 view的基础知识

    什么是view view extends View ViewGroup extends View

    3.1.2

    View的4个属性:

    top 左上角纵坐标 left 左上角横坐标 bottom 右下角纵坐标 right 右下角横坐标

    View的宽高和坐标关系:

    left = getLeft(); right= getRight(); top= getTop() bottom = getBottom();

    width = right -left; height = bottom - top;

    3.0新增参数:View平移的时候只有x,y,translationX,translationY改变

    x = left + translationX; y = top + tanslationY;

    3.1.3

    MotionEvent(运动事件)和TouchSlop (最小滑动距离)

    MotionEvent: MotionEvent.ACTION_DOWN 接触 MotionEvent.ACTION_MOVE 移动 MotionEvent.ACTION_UP 松开 getX/getY 当前view左上角x,y坐标 getRawX/getRawY 手机屏幕左上角x,y坐标 TouchSlop: ViewConfiguration.get(this).getScaledTouchSlop();常量

    3.1.4

    VelocityTracker (速度追踪)丶GestureDetector(手势检测器) 1.VelocityTracker (速度追踪): 速度 = (终点位置 - 起点位置)/时间段 手指逆着坐标系的正反向滑动,速度是负值

    @Override public boolean onTouchEvent(MotionEvent event) { //在view的onTouchEvent追踪点击事件的速度 VelocityTracker velocityTracker = VelocityTracker.obtain(); velocityTracker.addMovement(event); //1s内划过的像素 velocityTracker.computeCurrentVelocity(1000); int xVelocity = (int) velocityTracker.getXVelocity(); int yVelocity = (int) velocityTracker.getYVelocity(); //用完了重置回收 velocityTracker.clear(); velocityTracker.recycle(); return super.onTouchEvent(event); }

    2.GestureDetector(手势检测器):

    常用的方法:

    onSingleTapUp(单击)onFling(快速滑动)onScroll(拖动)onLongPress(长按)onDoubleTap(双击)

    建议:滑动相关,直接在onTouchEvent实现;双击使用GestureDetector

    3.2

    View的滑动 三种方式:

    1.使用scrollTo/scrollBy 2.动画平移 3.改变view的LayoutParams

    1.使用scrollTo/scrollBy

    scrollTo/scrollBy方法只能改变view内容的位置,不能改变view位置 从上往下滑动:getScrollY < 0 反之:getScrollY > 0 从左往右滑动:getScrollX < 0 反之:getScrollX > 0

    2.动画平移

    使用属性动画(>3.0) View v = null ; ObjectAnimator.ofFloat(v,”translationX”,0,100).setDuration(1000).start(); 3.0以前上述代码会出现:view移动了,”真身”还在原地,点击原地触发onClick 3.0以后没有问题了

    3.改变view的LayoutParams

    View v = null; ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) v.getLayoutParams(); layoutParams.width += 100; layoutParams.leftMargin += 100; v.requestLayout(); //或者 v.setLayoutParams(layoutParams);

    几种方式的比较:

    scrollTo/scrollBy:操作简单,适合view内容滑动 动画:不交互的view(点击事件故障) 改变view的layoutParams:操作复杂,适用于有交互的view

    3.3 Scroller(弹性滑动)

    1.使用Scroller实现弹性滑动 Scroller本身无法让View弹性滑动,它需要和View的computeScroll方法配合

    package com.weiwei.zx.wp; import android.content.Context; import android.view.View; import android.widget.Scroller; /** * Created by zx on 2016/1/7. */ public class MyView extends View { private Scroller mScroller; public MyView(Context context) { super(context); mScroller = new Scroller(context); //缓慢滚动到指定位置 smoothScrollTo(2,2); } private void smoothScrollTo(int destX, int destY) { int scrollX = getScrollX(); int delta = destX - scrollX; //1s内滑向destX,效果就是慢慢滑动 //startScroll(滑动的起点) mScroller.startScroll(scrollX,0,delta,0,1000); invalidate();//view重绘 } @Override public void computeScroll() { if(mScroller.computeScrollOffset()) { scrollTo(mScroller.getCurrX(),mScroller.getCurrY()); postInvalidate(); } } }

    原理:多次view重绘导致view多次小幅度滑动(弹性滑动)

    1.调用invalidate()不断让view重绘 2.通过重绘距滑动起始时间间隔,得到view当前滑动位置 3.通过scrollTo滑动

    2.使用动画实现弹性滑动(view的内容滑动)

    动画天然就具有弹性效果,思想和scroller类似

    3.使用延时策略

    思想:不断的发送延时消息,实现弹性效果(handle.postDelayed)

    3.4 View的事件分发机制

    1.touchEvent传递到顶层view的dipatchTouchEvent

    2.由dipatchTouchEvent分发;返回true,交给touchEvent处理;false交给onIntercepterTouchEvent处理

    3、onIntercepterTouchEvent返回true交给它的touchEvent处理,返回false传递给子view 总结:onInterceptTouchEvent是自rootiew向下传递, onTouchEvent正好相反。

    3.5 View的滑动冲突

    场景: 1.外部滑动方向和内部滑动方向不一致(viewpager+fragment) 2.外部滑动方向和内部滑动方向一致(listview+listview) 3.上面2中情况的嵌套

    解决方法:

    1.外部拦截法(通过滑动距离差,符合view的事件分发机制) 重写onInterceptTouchEvent方法,在方法中做相应拦截 2.内部拦截法(配合requestDisallowInterceptTouchEvent,和事件分发机制不一致) 推荐使用: 外部拦截法(简单易用)

    转载请注明原文地址: https://ju.6miu.com/read-810.html

    最新回复(0)