blob: 7236c2d1bb06a22777080e139d790b22bd97f42f [file] [log] [blame]
/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.launcher3.util;
import android.content.Context;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewConfiguration;
public class VerticalFlingDetector implements View.OnTouchListener {
private static final float CUSTOM_SLOP_MULTIPLIER = 2.2f;
private static final int SEC_IN_MILLIS = 1000;
private VelocityTracker mVelocityTracker;
private float mMinimumFlingVelocity;
private float mMaximumFlingVelocity;
private float mDownX, mDownY;
private boolean mShouldCheckFling;
private double mCustomTouchSlop;
public VerticalFlingDetector(Context context) {
ViewConfiguration vc = ViewConfiguration.get(context);
mMinimumFlingVelocity = vc.getScaledMinimumFlingVelocity();
mMaximumFlingVelocity = vc.getScaledMaximumFlingVelocity();
mCustomTouchSlop = CUSTOM_SLOP_MULTIPLIER * vc.getScaledTouchSlop();
}
@Override
public boolean onTouch(View v, MotionEvent ev) {
if (mVelocityTracker == null) {
mVelocityTracker = VelocityTracker.obtain();
}
mVelocityTracker.addMovement(ev);
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
mDownX = ev.getX();
mDownY = ev.getY();
mShouldCheckFling = false;
break;
case MotionEvent.ACTION_MOVE:
if (mShouldCheckFling) {
break;
}
if (Math.abs(ev.getY() - mDownY) > mCustomTouchSlop &&
Math.abs(ev.getY() - mDownY) > Math.abs(ev.getX() - mDownX)) {
mShouldCheckFling = true;
}
break;
case MotionEvent.ACTION_UP:
if (mShouldCheckFling) {
mVelocityTracker.computeCurrentVelocity(SEC_IN_MILLIS, mMaximumFlingVelocity);
// only when fling is detected in down direction
if (mVelocityTracker.getYVelocity() > mMinimumFlingVelocity) {
cleanUp();
return true;
}
}
// fall through.
case MotionEvent.ACTION_CANCEL:
cleanUp();
}
return false;
}
private void cleanUp() {
if (mVelocityTracker == null) {
return;
}
mVelocityTracker.recycle();
mVelocityTracker = null;
}
}