am d27f1cd3: Merge "Further refine touchMajor processing in ScaleGestureDetector" into jb-mr1-dev
* commit 'd27f1cd30b140f042e11032e4aa4381756e2998f': Further refine touchMajor processing in ScaleGestureDetector
This commit is contained in:
@@ -19,9 +19,6 @@ package android.view;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.SystemClock;
|
import android.os.SystemClock;
|
||||||
import android.util.FloatMath;
|
import android.util.FloatMath;
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Detects scaling transformation gestures using the supplied {@link MotionEvent}s.
|
* Detects scaling transformation gestures using the supplied {@link MotionEvent}s.
|
||||||
@@ -143,11 +140,16 @@ public class ScaleGestureDetector {
|
|||||||
private int mSpanSlop;
|
private int mSpanSlop;
|
||||||
private int mMinSpan;
|
private int mMinSpan;
|
||||||
|
|
||||||
private float[] mTouchHistoryLastAccepted;
|
// Bounds for recently seen values
|
||||||
private int[] mTouchHistoryDirection;
|
private float mTouchUpper;
|
||||||
private long[] mTouchHistoryLastAcceptedTime;
|
private float mTouchLower;
|
||||||
|
private float mTouchHistoryLastAccepted;
|
||||||
|
private int mTouchHistoryDirection;
|
||||||
|
private long mTouchHistoryLastAcceptedTime;
|
||||||
|
private int mTouchMinMajor;
|
||||||
|
|
||||||
private static final long TOUCH_STABILIZE_TIME = 128; // ms
|
private static final long TOUCH_STABILIZE_TIME = 128; // ms
|
||||||
|
private static final int TOUCH_MIN_MAJOR = 48; // dp
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Consistency verifier for debugging purposes.
|
* Consistency verifier for debugging purposes.
|
||||||
@@ -160,6 +162,8 @@ public class ScaleGestureDetector {
|
|||||||
mContext = context;
|
mContext = context;
|
||||||
mListener = listener;
|
mListener = listener;
|
||||||
mSpanSlop = ViewConfiguration.get(context).getScaledTouchSlop() * 2;
|
mSpanSlop = ViewConfiguration.get(context).getScaledTouchSlop() * 2;
|
||||||
|
mTouchMinMajor =
|
||||||
|
(int) (context.getResources().getDisplayMetrics().density * TOUCH_MIN_MAJOR + 0.5f);
|
||||||
mMinSpan = context.getResources().getDimensionPixelSize(
|
mMinSpan = context.getResources().getDimensionPixelSize(
|
||||||
com.android.internal.R.dimen.config_minScalingSpan);
|
com.android.internal.R.dimen.config_minScalingSpan);
|
||||||
}
|
}
|
||||||
@@ -172,81 +176,55 @@ public class ScaleGestureDetector {
|
|||||||
private void addTouchHistory(MotionEvent ev) {
|
private void addTouchHistory(MotionEvent ev) {
|
||||||
final long currentTime = SystemClock.uptimeMillis();
|
final long currentTime = SystemClock.uptimeMillis();
|
||||||
final int count = ev.getPointerCount();
|
final int count = ev.getPointerCount();
|
||||||
|
boolean accept = currentTime - mTouchHistoryLastAcceptedTime >= TOUCH_STABILIZE_TIME;
|
||||||
|
float total = 0;
|
||||||
|
int sampleCount = 0;
|
||||||
for (int i = 0; i < count; i++) {
|
for (int i = 0; i < count; i++) {
|
||||||
final int id = ev.getPointerId(i);
|
final boolean hasLastAccepted = !Float.isNaN(mTouchHistoryLastAccepted);
|
||||||
ensureTouchHistorySize(id);
|
|
||||||
|
|
||||||
final boolean hasLastAccepted = !Float.isNaN(mTouchHistoryLastAccepted[id]);
|
|
||||||
boolean accept = true;
|
|
||||||
final int historySize = ev.getHistorySize();
|
final int historySize = ev.getHistorySize();
|
||||||
for (int h = 0; h < historySize + 1; h++) {
|
final int pointerSampleCount = historySize + 1;
|
||||||
final float major;
|
for (int h = 0; h < pointerSampleCount; h++) {
|
||||||
final float minor;
|
float major;
|
||||||
if (h < historySize) {
|
if (h < historySize) {
|
||||||
major = ev.getHistoricalTouchMajor(i, h);
|
major = ev.getHistoricalTouchMajor(i, h);
|
||||||
minor = ev.getHistoricalTouchMinor(i, h);
|
|
||||||
} else {
|
} else {
|
||||||
major = ev.getTouchMajor(i);
|
major = ev.getTouchMajor(i);
|
||||||
minor = ev.getTouchMinor(i);
|
|
||||||
}
|
}
|
||||||
final float avg = (major + minor) / 2;
|
if (major < mTouchMinMajor) major = mTouchMinMajor;
|
||||||
|
total += major;
|
||||||
|
|
||||||
|
if (Float.isNaN(mTouchUpper) || major > mTouchUpper) {
|
||||||
|
mTouchUpper = major;
|
||||||
|
}
|
||||||
|
if (Float.isNaN(mTouchLower) || major < mTouchLower) {
|
||||||
|
mTouchLower = major;
|
||||||
|
}
|
||||||
|
|
||||||
if (hasLastAccepted) {
|
if (hasLastAccepted) {
|
||||||
final int directionSig = (int) Math.signum(avg - mTouchHistoryLastAccepted[id]);
|
final int directionSig = (int) Math.signum(major - mTouchHistoryLastAccepted);
|
||||||
if (directionSig != mTouchHistoryDirection[id] ||
|
if (directionSig != mTouchHistoryDirection ||
|
||||||
(directionSig == 0 && mTouchHistoryDirection[id] == 0)) {
|
(directionSig == 0 && mTouchHistoryDirection == 0)) {
|
||||||
mTouchHistoryDirection[id] = directionSig;
|
mTouchHistoryDirection = directionSig;
|
||||||
final long time = h < historySize ? ev.getHistoricalEventTime(h)
|
final long time = h < historySize ? ev.getHistoricalEventTime(h)
|
||||||
: ev.getEventTime();
|
: ev.getEventTime();
|
||||||
mTouchHistoryLastAcceptedTime[id] = time;
|
mTouchHistoryLastAcceptedTime = time;
|
||||||
accept = false;
|
|
||||||
}
|
|
||||||
if (currentTime - mTouchHistoryLastAcceptedTime[id] < TOUCH_STABILIZE_TIME) {
|
|
||||||
accept = false;
|
accept = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
sampleCount += pointerSampleCount;
|
||||||
if (accept) {
|
|
||||||
float newAccepted = (ev.getTouchMajor(i) + ev.getTouchMinor(i)) / 2;
|
|
||||||
if (hasLastAccepted) {
|
|
||||||
newAccepted = (mTouchHistoryLastAccepted[id] + newAccepted) / 2;
|
|
||||||
}
|
|
||||||
mTouchHistoryLastAccepted[id] = newAccepted;
|
|
||||||
mTouchHistoryDirection[id] = 0;
|
|
||||||
mTouchHistoryLastAcceptedTime[id] = ev.getEventTime();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
final float avg = total / sampleCount;
|
||||||
* Clear out the touch history for a given pointer id.
|
|
||||||
* @param id pointer id to clear
|
|
||||||
* @see #addTouchHistory(MotionEvent)
|
|
||||||
*/
|
|
||||||
private boolean removeTouchHistoryForId(int id) {
|
|
||||||
if (id >= mTouchHistoryLastAccepted.length) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
mTouchHistoryLastAccepted[id] = Float.NaN;
|
|
||||||
mTouchHistoryDirection[id] = 0;
|
|
||||||
mTouchHistoryLastAcceptedTime[id] = 0;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
if (accept) {
|
||||||
* Get the adjusted combined touchMajor/touchMinor value for a given pointer id
|
float newAccepted = (mTouchUpper + mTouchLower + avg) / 3;
|
||||||
* @param id the pointer id of the data to obtain
|
mTouchUpper = (mTouchUpper + newAccepted) / 2;
|
||||||
* @return the adjusted major/minor value for the point at id
|
mTouchLower = (mTouchLower + newAccepted) / 2;
|
||||||
* @see #addTouchHistory(MotionEvent)
|
mTouchHistoryLastAccepted = newAccepted;
|
||||||
*/
|
mTouchHistoryDirection = 0;
|
||||||
private float getAdjustedTouchHistory(int id) {
|
mTouchHistoryLastAcceptedTime = ev.getEventTime();
|
||||||
if (id >= mTouchHistoryLastAccepted.length) {
|
|
||||||
Log.e(TAG, "Error retrieving adjusted touch history for id=" + id +
|
|
||||||
" - incomplete event stream?");
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
return mTouchHistoryLastAccepted[id];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -254,41 +232,11 @@ public class ScaleGestureDetector {
|
|||||||
* @see #addTouchHistory(MotionEvent)
|
* @see #addTouchHistory(MotionEvent)
|
||||||
*/
|
*/
|
||||||
private void clearTouchHistory() {
|
private void clearTouchHistory() {
|
||||||
if (mTouchHistoryLastAccepted == null) {
|
mTouchUpper = Float.NaN;
|
||||||
// All three arrays will be null if this is the case; nothing to do.
|
mTouchLower = Float.NaN;
|
||||||
return;
|
mTouchHistoryLastAccepted = Float.NaN;
|
||||||
}
|
mTouchHistoryDirection = 0;
|
||||||
Arrays.fill(mTouchHistoryLastAccepted, Float.NaN);
|
mTouchHistoryLastAcceptedTime = 0;
|
||||||
Arrays.fill(mTouchHistoryDirection, 0);
|
|
||||||
Arrays.fill(mTouchHistoryLastAcceptedTime, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ensureTouchHistorySize(int id) {
|
|
||||||
final int requiredSize = id + 1;
|
|
||||||
if (mTouchHistoryLastAccepted == null || mTouchHistoryLastAccepted.length < requiredSize) {
|
|
||||||
final float[] newLastAccepted = new float[requiredSize];
|
|
||||||
final int[] newDirection = new int[requiredSize];
|
|
||||||
final long[] newLastAcceptedTime = new long[requiredSize];
|
|
||||||
|
|
||||||
int oldLength = 0;
|
|
||||||
if (mTouchHistoryLastAccepted != null) {
|
|
||||||
System.arraycopy(mTouchHistoryLastAccepted, 0, newLastAccepted, 0,
|
|
||||||
mTouchHistoryLastAccepted.length);
|
|
||||||
System.arraycopy(mTouchHistoryDirection, 0, newDirection, 0,
|
|
||||||
mTouchHistoryDirection.length);
|
|
||||||
System.arraycopy(mTouchHistoryLastAcceptedTime, 0, newLastAcceptedTime, 0,
|
|
||||||
mTouchHistoryLastAcceptedTime.length);
|
|
||||||
oldLength = mTouchHistoryLastAccepted.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
Arrays.fill(newLastAccepted, oldLength, newLastAccepted.length, Float.NaN);
|
|
||||||
Arrays.fill(newDirection, oldLength, newDirection.length, 0);
|
|
||||||
Arrays.fill(newLastAcceptedTime, oldLength, newLastAcceptedTime.length, 0);
|
|
||||||
|
|
||||||
mTouchHistoryLastAccepted = newLastAccepted;
|
|
||||||
mTouchHistoryDirection = newDirection;
|
|
||||||
mTouchHistoryLastAcceptedTime = newLastAcceptedTime;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -346,23 +294,16 @@ public class ScaleGestureDetector {
|
|||||||
final float focusX = sumX / div;
|
final float focusX = sumX / div;
|
||||||
final float focusY = sumY / div;
|
final float focusY = sumY / div;
|
||||||
|
|
||||||
if (pointerUp) {
|
|
||||||
final int id = event.getPointerId(event.getActionIndex());
|
addTouchHistory(event);
|
||||||
if (!removeTouchHistoryForId(id)) {
|
|
||||||
Log.e(TAG, "Got ACTION_POINTER_UP for previously unknown id=" + id +
|
|
||||||
" - incomplete event stream?");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
addTouchHistory(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Determine average deviation from focal point
|
// Determine average deviation from focal point
|
||||||
float devSumX = 0, devSumY = 0;
|
float devSumX = 0, devSumY = 0;
|
||||||
for (int i = 0; i < count; i++) {
|
for (int i = 0; i < count; i++) {
|
||||||
if (skipIndex == i) continue;
|
if (skipIndex == i) continue;
|
||||||
|
|
||||||
// Average touch major and touch minor and convert the resulting diameter into a radius.
|
// Convert the resulting diameter into a radius.
|
||||||
final float touchSize = getAdjustedTouchHistory(event.getPointerId(i)) / 2;
|
final float touchSize = mTouchHistoryLastAccepted / 2;
|
||||||
devSumX += Math.abs(event.getX(i) - focusX) + touchSize;
|
devSumX += Math.abs(event.getX(i) - focusX) + touchSize;
|
||||||
devSumY += Math.abs(event.getY(i) - focusY) + touchSize;
|
devSumY += Math.abs(event.getY(i) - focusY) + touchSize;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user