Android 获取控件滑动速度,速度跟踪器VelocityTracker;
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;的更多相关文章
- Android 获取控件相对于屏幕位置
// View宽,高 public int[] getLocation(View v) { int[] loc = new int[4]; int[] location = new int[2]; v ...
- Android自动化测试中AccessibilityService获取控件信息(1)
Android自动化测试中AccessibilityService获取控件信息(1) 分类: android自动化测试2014-03-24 15:31 3455人阅读 评论(16) 收藏 举报 and ...
- Android自动化测试中AccessibilityService获取控件信息(2)-三种方式对比
Android自动化测试中AccessibilityService获取控件信息(2)-三种方式对比 上一篇文章: Android自动化测试中AccessibilityService获取控件信息(1 ...
- 从零开始学android开发-获取控件
mBtnNews = (Button)findViewById(R.id.btn_news);//获取控件
- android获取屏幕宽高与获取控件宽高
获取屏幕宽高 // 获取屏幕宽高(方法1) int screenWidth = getWindowManager().getDefaultDisplay().getWidth(); // 屏幕宽(像素 ...
- android 获取屏幕宽高 和 获取控件坐标
一.获取屏幕宽高: (1). WindowManager wm = (WindowManager)getSystemService(Context.WINDOW_SERVICE); int width ...
- 【Android】获取控件的宽和高
有时候我们须要在Activity的时候获取控件的宽和高来做一些操作,以下介绍三种获取宽和高的方式: 1. onWindowFocusChanged @Override public void onWi ...
- android 获取屏幕的高度和宽度、获取控件在屏幕中的位置、获取屏幕中控件的高度和宽度
(一)获取屏幕的高度和宽度 有两种方法: 方法1: WindowManager wm = (WindowManager) getContext().getSystemService(Context.W ...
- Android 在OnCreate()中获取控件高度与宽度
试过在OnCreate()中获取控件高度与宽度的童鞋都知道,getWidth()与getHeight()方法返回是0,具体原因 看一下Activity的生命周期 就会明白. 上代码: 方法一: int ...
随机推荐
- c函数创建文件和路径
bool NewFileName(const char* filename) { size_t len; < (len = strlen(filename))) { char* tmpbuf, ...
- centos 安装桌面系统
yum -y groupinstall "Desktop" "Desktop Platform" "X Window System" &qu ...
- 深入path类
Path类放在System.IO命名空间里.Path是一个只包含有静态方法的实例类,所以它不需要在使用之前实例化.它有各种方法用于处理文件的扩展名.文件名.根路径,以及和更多和路径相关的方面.下面就是 ...
- 带通滤波 matlab
巴特沃斯:1.带阻滤波器设计带阻滤波器指标:阻带上边界频率:5Kz:阻带下边界频率:7Kz:通带上边界频率:2Kz:通带下边界频率:9Kz:通带最大衰减:1dB:阻带最小衰减:20dB:设计程序如下: ...
- More is better
题目描述: Mr Wang wants some boys to help him with a project. Because the project is rather complex, the ...
- dos脚本2
一.简单批处理内部命令简介 1.Echo 命令 打开回显或关闭请求回显功能,或显示消息.如果没有任何参数,echo 命令将显示当 前回显设置. 语法 echo [{on off}] [mess ...
- 改善Python程序的条条建议
1:引论 建议1.理解Pythonic概念—-详见Python中的<Python之禅> 建议2.编写Pythonic代码 避免不规范代码,比如只用大小写区分变量.使用容易混淆的变量名. ...
- 百度前端代码规范:HTML
HTML 1.代码风格 1.1缩进与换行 [强制] 使用 4 个空格做为一个缩进层级,不允许使用 2 个空格 或 tab 字符. <style> ul { padding:; } < ...
- 《从Lucene到Elasticsearch:全文检索实战》学习笔记一
今天,我主要给大家讲一下信息检索概念. 信息检索: 互联网时代的飞速发展使人们进入了信息爆炸时代,据统计全球的互联网用户已达到30亿,在各个网站及移动app在每个分钟 产生的数据量是巨大的,从而导致数 ...
- day03运算符 逻辑运算符
今日内容 运算符 算术运算符 取模% 打印1~100基数 #模2余1的为基数 #以1 3 5 7 9结尾的为奇数 # count =1 # while count<100: # print(co ...