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

阅读本章你将了解:

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,和事件分发机制不一致)
推荐使用:
外部拦截法(简单易用)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值