VelocityTracker 速度跟踪器

在写关于Android滑动的控件,如果用户手指在屏幕上(当前位置 - 起始位置 > 某个数值)就做一个界面切换,但是总感觉太生硬,只有满足上面的条件才会触发切换界面,不管用户滑动的速度有多么的快,都要去算当前位置和起始位置的距离;但是ViewPager这个控件如果你滑动速度很快的话,就触发切换页面的效果了,怎么实现的呢;于是我去看了一下Google的ViewPager的源码,发现了这么个神器的东西:VelocityTracker;

以下是Viewpager的源码:

 @Override
public boolean onTouchEvent(MotionEvent ev) {
if (mFakeDragging) {
// A fake drag is in progress already, ignore this real one
// but still eat the touch events.
// (It is likely that the user is multi-touching the screen.)
return true;
} if (ev.getAction() == MotionEvent.ACTION_DOWN && ev.getEdgeFlags() != 0) {
// Don't handle edge touches immediately -- they may actually belong to one of our
// descendants.
return false;
} if (mAdapter == null || mAdapter.getCount() == 0) {
// Nothing to present or scroll; nothing to touch.
return false;
} if (mVelocityTracker == null) {
mVelocityTracker = VelocityTracker.obtain();
}
mVelocityTracker.addMovement(ev); final int action = ev.getAction();
boolean needsInvalidate = false; switch (action & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN: {
mScroller.abortAnimation();
mPopulatePending = false;
populate(); // Remember where the motion event started
mLastMotionX = mInitialMotionX = ev.getX();
mLastMotionY = mInitialMotionY = ev.getY();
mActivePointerId = ev.getPointerId(0);
break;
}
case MotionEvent.ACTION_MOVE:
if (!mIsBeingDragged) {
final int pointerIndex = ev.findPointerIndex(mActivePointerId);
if (pointerIndex == -1) {
// A child has consumed some touch events and put us into an inconsistent
// state.
needsInvalidate = resetTouch();
break;
}
final float x = ev.getX(pointerIndex);
final float xDiff = Math.abs(x - mLastMotionX);
final float y = ev.getY(pointerIndex);
final float yDiff = Math.abs(y - mLastMotionY);
if (DEBUG) {
Log.v(TAG, "Moved x to " + x + "," + y + " diff=" + xDiff + "," + yDiff);
}
if (xDiff > mTouchSlop && xDiff > yDiff) {
if (DEBUG) Log.v(TAG, "Starting drag!");
mIsBeingDragged = true;
requestParentDisallowInterceptTouchEvent(true);
mLastMotionX = x - mInitialMotionX > 0 ? mInitialMotionX + mTouchSlop :
mInitialMotionX - mTouchSlop;
mLastMotionY = y;
setScrollState(SCROLL_STATE_DRAGGING);
setScrollingCacheEnabled(true); // Disallow Parent Intercept, just in case
ViewParent parent = getParent();
if (parent != null) {
parent.requestDisallowInterceptTouchEvent(true);
}
}
}
// Not else! Note that mIsBeingDragged can be set above.
if (mIsBeingDragged) {
// Scroll to follow the motion event
final int activePointerIndex = ev.findPointerIndex(mActivePointerId);
final float x = ev.getX(activePointerIndex);
needsInvalidate |= performDrag(x);
}
break;
case MotionEvent.ACTION_UP:
if (mIsBeingDragged) {
final VelocityTracker velocityTracker = mVelocityTracker;
velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
int initialVelocity = (int) velocityTracker.getXVelocity(mActivePointerId);
mPopulatePending = true;
final int width = getClientWidth();
final int scrollX = getScrollX();
final ItemInfo ii = infoForCurrentScrollPosition();
final float marginOffset = (float) mPageMargin / width;
final int currentPage = ii.position;
final float pageOffset = (((float) scrollX / width) - ii.offset)
/ (ii.widthFactor + marginOffset);
final int activePointerIndex = ev.findPointerIndex(mActivePointerId);
final float x = ev.getX(activePointerIndex);
final int totalDelta = (int) (x - mInitialMotionX);
int nextPage = determineTargetPage(currentPage, pageOffset, initialVelocity,
totalDelta);
setCurrentItemInternal(nextPage, true, true, initialVelocity); needsInvalidate = resetTouch();
}
break;
case MotionEvent.ACTION_CANCEL:
if (mIsBeingDragged) {
scrollToItem(mCurItem, true, 0, false);
needsInvalidate = resetTouch();
}
break;
case MotionEvent.ACTION_POINTER_DOWN: {
final int index = ev.getActionIndex();
final float x = ev.getX(index);
mLastMotionX = x;
mActivePointerId = ev.getPointerId(index);
break;
}
case MotionEvent.ACTION_POINTER_UP:
onSecondaryPointerUp(ev);
mLastMotionX = ev.getX(ev.findPointerIndex(mActivePointerId));
break;
}
if (needsInvalidate) {
ViewCompat.postInvalidateOnAnimation(this);
}
return true;
}

有这么几行代码:

        if (mVelocityTracker == null) {

            mVelocityTracker = VelocityTracker.obtain();

        }

        mVelocityTracker.addMovement(ev);

final VelocityTracker velocityTracker = mVelocityTracker;

                    velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);

                    int initialVelocity = (int) velocityTracker.getXVelocity(mActivePointerId);

它在Touch中实例化VelocityTracker ,在UP触摸事件中获取到当前的速度;

可以仿着写个自定义的View:

public class ContinueSlideScrollView extends NestedScrollView {

    private final String TAG = "CCB";

    public ContinueSlideScrollView(Context context) {
super(context);
this.context = context;
} public ContinueSlideScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
} public ContinueSlideScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.context = context;
} @Override
public boolean onTouchEvent(MotionEvent ev) {
if (mVelocityTracker == null) {
mVelocityTracker = VelocityTracker.obtain();
}
mVelocityTracker.addMovement(ev); switch (ev.getAction()){
case MotionEvent.ACTION_DOWN: break;
case MotionEvent.ACTION_MOVE: break;
case MotionEvent.ACTION_UP: final VelocityTracker velocityTracker = mVelocityTracker;
velocityTracker.computeCurrentVelocity(1000, ViewConfiguration.get(context).getScaledMaximumFlingVelocity());
int initialVelocity = (int) velocityTracker.getYVelocity();
Log.i(TAG, initialVelocity>0 ? "向下滑动,速度是:"+initialVelocity : "向上滑动,速度是:"+initialVelocity);
break;
}
return super.onTouchEvent(ev);
} @Override
protected void onDetachedFromWindow() {
mVelocityTracker.recycle();
super.onDetachedFromWindow();
}
}

获取到当前View的滑动速度后,你就可以对它胡作非为了!!!

Android 获取控件滑动速度,速度跟踪器VelocityTracker;的更多相关文章

  1. Android 获取控件相对于屏幕位置

    // View宽,高 public int[] getLocation(View v) { int[] loc = new int[4]; int[] location = new int[2]; v ...

  2. Android自动化测试中AccessibilityService获取控件信息(1)

    Android自动化测试中AccessibilityService获取控件信息(1) 分类: android自动化测试2014-03-24 15:31 3455人阅读 评论(16) 收藏 举报 and ...

  3. Android自动化测试中AccessibilityService获取控件信息(2)-三种方式对比

    Android自动化测试中AccessibilityService获取控件信息(2)-三种方式对比   上一篇文章: Android自动化测试中AccessibilityService获取控件信息(1 ...

  4. 从零开始学android开发-获取控件

    mBtnNews = (Button)findViewById(R.id.btn_news);//获取控件

  5. android获取屏幕宽高与获取控件宽高

    获取屏幕宽高 // 获取屏幕宽高(方法1) int screenWidth = getWindowManager().getDefaultDisplay().getWidth(); // 屏幕宽(像素 ...

  6. android 获取屏幕宽高 和 获取控件坐标

    一.获取屏幕宽高: (1). WindowManager wm = (WindowManager)getSystemService(Context.WINDOW_SERVICE); int width ...

  7. 【Android】获取控件的宽和高

    有时候我们须要在Activity的时候获取控件的宽和高来做一些操作,以下介绍三种获取宽和高的方式: 1. onWindowFocusChanged @Override public void onWi ...

  8. android 获取屏幕的高度和宽度、获取控件在屏幕中的位置、获取屏幕中控件的高度和宽度

    (一)获取屏幕的高度和宽度 有两种方法: 方法1: WindowManager wm = (WindowManager) getContext().getSystemService(Context.W ...

  9. Android 在OnCreate()中获取控件高度与宽度

    试过在OnCreate()中获取控件高度与宽度的童鞋都知道,getWidth()与getHeight()方法返回是0,具体原因 看一下Activity的生命周期 就会明白. 上代码: 方法一: int ...

随机推荐

  1. Awesome Tools

    Awesome R: https://awesome-r.com/ (Chinese translation: http://www.ppvke.com/Blog/archives/40981) Aw ...

  2. intelij idea设置成eclipse快捷键

    1.导入jar包文件: https://pan.baidu.com/s/1QSd_CY5X_dUUw74evbckXg  密码: 23rq 2.idea -->settting ---> ...

  3. c# 抽象类与接口【学习笔记】

    最近一直在学着面向接口编程,总是会写出好多的接口然后继承,现在开始发现了一些好处,就是在一个方法里面使用另一个方法的时候, 用接口代替这个被使用的方法,可以减少代码的耦合,后期的扩展也方便,代码易于维 ...

  4. 发布-订阅消息系统Kafka简介

    转载请注明出处:http://www.cnblogs.com/BYRans/ Kafka是由Apache软件基金会开发的一个开源流处理平台,由Scala和Java编写.Kafka是一种高吞吐量的分布式 ...

  5. 博弈论:寻找先手必胜策略——Grundy值

    选修了人工智能课程,老师布置了调研任务:Grundy,开始看了一些资料并没有看懂. 后来找到了一篇文,写的很棒,里面有好多博弈相关的问题与分析,分享出来给大家: http://endless.logd ...

  6. 北大poj- 1006

    生理周期 Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 133189   Accepted: 42577 Descripti ...

  7. Linux 驱动——从宏观上掌握基本框架

    一.一个简单的驱动程序实例 led_drv.c 驱动文件: #include <linux/module.h>#include <linux/kernel.h>#include ...

  8. Day 1: ASP.NET and JavaScript Jan.16th Trying

    ASP.NET has its own named controls(tags) corresponding to that in an HTML document, such as <asp: ...

  9. 第七十九课 最短路径(Floyd)

    程序如下: #ifndef GRAPH_H #define GRAPH_H #include "Object.h" #include "SharedPointer.h&q ...

  10. scrapy框架之递归解析和post请求

    递归爬取解析多页页面数据 scrapy核心组件工作流程 scrapy的post请求发送 1.递归爬取解析多页页面数据 - 需求:将糗事百科所有页码的作者和段子内容数据进行爬取切持久化存储 - 需求分析 ...