下面列出了android.view.MotionEvent#getHistorySize ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
public boolean init(View view, MotionEvent event) {
// We must have history available to calc the dx. Normally it's there - if it isn't temporarily,
// we declare the event 'invalid' and expect it in consequent events.
if (event.getHistorySize() == 0) {
return false;
}
// Allow for counter-orientation-direction operations (e.g. item swiping) to run fluently.
final float dy = event.getY(0) - event.getHistoricalY(0, 0);
final float dx = event.getX(0) - event.getHistoricalX(0, 0);
if (Math.abs(dx) < Math.abs(dy)) {
return false;
}
mAbsOffset = view.getTranslationX();
mDeltaOffset = dx;
mDir = mDeltaOffset > 0;
return true;
}
/**
* adjust header padding according to motion event
*
* @param ev
*/
private void adjustHeaderPadding(MotionEvent ev) {
// adjust header padding according to motion event history
int pointerCount = ev.getHistorySize();
if (isVerticalFadingEdgeEnabled()) {
setVerticalScrollBarEnabled(false);
}
for (int i = 0; i < pointerCount; i++) {
if (currentHeaderStatus == HEADER_STATUS_DROP_DOWN_TO_LOAD
|| currentHeaderStatus == HEADER_STATUS_RELEASE_TO_LOAD) {
headerLayout
.setPadding(
headerLayout.getPaddingLeft(),
(int) (((ev.getHistoricalY(i) - actionDownPointY) - headerOriginalHeight) / headerPaddingTopRate),
headerLayout.getPaddingRight(), headerLayout.getPaddingBottom());
}
}
}
/**
* Helper method to debug the motion events.
*/
private static String printToString(MotionEvent ev) {
int historySize = ev.getHistorySize();
int pointerCount = ev.getPointerCount();
StringBuilder resultString = new StringBuilder();
for (int h = 0; h < historySize; h++) {
resultString.append(String.format("At time %d:", ev.getHistoricalEventTime(h)));
for (int p = 0; p < pointerCount; p++) {
resultString.append(String.format(" pointer %d %s: (%f, %f)",
ev.getPointerId(p), MotionEvent.actionToString(ev.getActionMasked()),
ev.getHistoricalX(p, h), ev.getHistoricalY(p, h)));
}
}
resultString.append(String.format("At time %d:", ev.getEventTime()));
for (int p = 0; p < pointerCount; p++) {
resultString.append(String.format(" pointer %d %s: (%f, %f)",
ev.getPointerId(p), MotionEvent.actionToString(ev.getActionMasked()),
ev.getX(p), ev.getY(p)));
}
return resultString.toString();
}
/**
* <p>Calculates the pinch velocity for the last <code>timeWindow</code> milliseconds.</p>
* @param event
* @param pointerA id of pointer A
* @param pointerB id of pointer B
* @param timeWindow
* @return spacing between both pointers
*/
public static final float pinchVelocity(MotionEvent event, int pointerA, int pointerB, long timeWindow) {
int indexA = event.findPointerIndex(pointerA);
int indexB = event.findPointerIndex(pointerB);
long eventTime = event.getEventTime();
long timeDelta = 0;
float previousSpacing = spacingByIndex(event, indexA, indexB);
float scale = 1;
for(int i = 0, n = event.getHistorySize(); i < n && timeDelta < timeWindow; i++) {
int index = (n - 1) - i;
float x = event.getHistoricalX(indexA, index) - event.getHistoricalX(indexB, index);
float y = event.getHistoricalY(indexA, index) - event.getHistoricalY(indexB, index);
float spacing = (float) Math.sqrt(x * x + y * y);
scale *= previousSpacing / spacing;
previousSpacing = spacing;
timeDelta = eventTime - event.getHistoricalEventTime(index);
}
return (float) Math.pow(Math.pow(scale, 1d / timeWindow), 1000d);
}
public boolean init(View view, MotionEvent event) {
// We must have history available to calc the dx. Normally it's there - if it isn't temporarily,
// we declare the event 'invalid' and expect it in consequent events.
if (event.getHistorySize() == 0) {
return false;
}
// Allow for counter-orientation-direction operations (e.g. item swiping) to run fluently.
final float dy = event.getY(0) - event.getHistoricalY(0, 0);
final float dx = event.getX(0) - event.getHistoricalX(0, 0);
if (Math.abs(dx) > Math.abs(dy)) {
return false;
}
mAbsOffset = view.getTranslationY();
mDeltaOffset = dy;
mDir = mDeltaOffset > 0;
return true;
}
@Override
public boolean onTouch(View v, MotionEvent event) {
int histLen = event.getHistorySize();
for (int i = 0; i < histLen; i++){
UsMotionEvent eh = new UsMotionEvent(event, waltDevice.clock.baseTime, i);
touchEventList.add(eh);
}
UsMotionEvent e = new UsMotionEvent(event, waltDevice.clock.baseTime);
touchEventList.add(e);
moveCount += histLen + 1;
updateCountsDisplay();
return true;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
float eventX = event.getX();
float eventY = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
path.moveTo(eventX, eventY);
return true;
case MotionEvent.ACTION_MOVE:
case MotionEvent.ACTION_UP:
// When the hardware tracks events faster than they are delivered,
// the event will contain a history of those skipped points.
int historySize = event.getHistorySize();
for (int i = 0; i < historySize; i++) {
float historicalX = event.getHistoricalX(i);
float historicalY = event.getHistoricalY(i);
path.lineTo(historicalX, historicalY);
}
path.lineTo(eventX, eventY);
break;
default:
return false;
}
// Schedules a repaint.
invalidate();
return true;
}
void addMovement(MotionEvent ev) {
long time = ev.getEventTime();
final int N = ev.getHistorySize();
for (int i=0; i<N; i++) {
addPoint(ev.getHistoricalX(i), ev.getHistoricalY(i),
ev.getHistoricalEventTime(i));
}
addPoint(ev.getX(), ev.getY(), time);
}
public boolean init(View view, MotionEvent event) {
// We must have history available to calc the dx. Normally it's there - if it isn't temporarily,
// we declare the event 'invalid' and expect it in consequent events.
if (event.getHistorySize() == 0) {
return false;
}
// Allow for counter-orientation-direction operations (e.g. item swiping) to run fluently.
final float dy = event.getY(0) - event.getHistoricalY(0, 0);
final float dx = event.getX(0) - event.getHistoricalX(0, 0);
if (Math.abs(dx) > Math.abs(dy)) {
return false;
}
if( dy == 0.f ) { // just click event
return false;
}
// mAbsOffset = view.getTranslationY();
mAbsOffset = getViewOffset(view);
mDeltaOffset = dy;
mDir = mDeltaOffset > 0;
Log.d("wxy-motion", String.format("mAbsOffset %s mDeltaOffset %s", mAbsOffset, mDeltaOffset));
Log.d("wxy-motion","mDir = " + mDir);
return true;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
int x = (int) event.getX();
int y = (int) event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
sigPoints.add(new LinePathPoint(x, y, LinePathPoint.TYPE_LINE_START));
if (sigPath.isEmpty()) {
callbacks.onSignatureStarted();
}
sigPath.moveTo(x, y);
invalidate();
break;
case MotionEvent.ACTION_MOVE:
case MotionEvent.ACTION_UP:
int hSize = event.getHistorySize();
for (int i = 0; i < hSize; i++) {
int hX = (int) event.getHistoricalX(i);
int hY = (int) event.getHistoricalY(i);
sigPath.lineTo(hX, hY);
sigPoints.add(new LinePathPoint(x, y, LinePathPoint.TYPE_LINE_POINT));
}
sigPath.lineTo(x, y);
sigPoints.add(new LinePathPoint(x, y, LinePathPoint.TYPE_LINE_POINT));
invalidate();
break;
}
return true;
}
public void addMovement(MotionEvent ev) {
long time = ev.getEventTime();
final int N = ev.getHistorySize();
for (int i = 0; i < N; i++) {
addPoint(ev.getHistoricalX(i), ev.getHistoricalY(i),
ev.getHistoricalEventTime(i));
}
addPoint(ev.getX(), ev.getY(), time);
}
@Override
public boolean onTrackballEvent(MotionEvent event)
{
int action = event.getAction();
switch (action)
{
case MotionEvent.ACTION_UP:
setFollowingThroughContext(!isFollowing);
break;
case MotionEvent.ACTION_MOVE:
if (!isFollowing)
{
int n = event.getHistorySize();
final float scaleX = event.getXPrecision();
final float scaleY = event.getYPrecision();
int dx = (int) (-event.getX() * scaleX);
int dy = (int) (-event.getY() * scaleY);
for (int i = 0; i < n; i++)
{
dx += -event.getHistoricalX(i) * scaleX;
dy += -event.getHistoricalY(i) * scaleY;
}
if (Math.abs(dx) > 0 || Math.abs(dy) > 0)
{
onDragFinished(dx, dy);
}
}
break;
}
/*
* for (MapOverlay mo : this.overlays) if (mo.onTrackballEvent(event,
* this)) return true;
*/
return true;
}
@Override
public boolean onTouchEvent(@NonNull MotionEvent event) {
if (mUiState.getLocked()) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mUiState.setLockBusy(true);
return true;
case MotionEvent.ACTION_UP:
mUiState.setLockBusy(false);
return true;
case MotionEvent.ACTION_MOVE:
return true;
}
return false;
}
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mLastX = event.getX();
mLastY = event.getY();
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_MOVE:
break;
default:
return false;
}
PhononMutable phm = mUiState.getPhononMutable();
for (int i = 0; i < event.getHistorySize(); i++) {
touchLine(phm, event.getHistoricalX(i), event.getHistoricalY(i));
}
touchLine(phm, event.getX(), event.getY());
if (mUiState.sendIfDirty()) {
invalidate();
}
return true;
}
public boolean onGenericMotionEvent(MotionEvent event) {
if (0 == mDPadState) {
// Process all historical movement samples in the batch.
final int historySize = event.getHistorySize();
for (int i = 0; i < historySize; i++) {
processJoystickInput(event, i);
}
// Process the current movement sample in the batch.
processJoystickInput(event, -1);
}
return true;
}
@Override
public boolean onGenericMotionEvent(MotionEvent event) {
ensureInitialized();
// Check that the event came from a joystick since a generic motion event
// could be almost anything.
if ((event.getSource() & InputDevice.SOURCE_CLASS_JOYSTICK) != 0
&& event.getAction() == MotionEvent.ACTION_MOVE) {
// Cache the most recently obtained device information.
// The device information may change over time but it can be
// somewhat expensive to query.
if (mLastInputDevice == null || mLastInputDevice.getId() != event.getDeviceId()) {
mLastInputDevice = event.getDevice();
// It's possible for the device id to be invalid.
// In that case, getDevice() will return null.
if (mLastInputDevice == null) {
return false;
}
}
// Ignore joystick while the DPad is pressed to avoid conflicting motions.
if (mDPadState != 0) {
return true;
}
// Process all historical movement samples in the batch.
final int historySize = event.getHistorySize();
for (int i = 0; i < historySize; i++) {
processJoystickInput(event, i);
}
// Process the current movement sample in the batch.
processJoystickInput(event, -1);
return true;
}
return super.onGenericMotionEvent(event);
}
private void onMoveEvent(final int x, final int y, final long eventTime, final MotionEvent me) {
if (DEBUG_MOVE_EVENT) {
printTouchEvent("onMoveEvent:", x, y, eventTime);
}
if (mIsTrackingForActionDisabled) {
return;
}
if (sGestureEnabler.shouldHandleGesture() && me != null) {
// Add historical points to gesture path.
final int pointerIndex = me.findPointerIndex(mPointerId);
final int historicalSize = me.getHistorySize();
for (int h = 0; h < historicalSize; h++) {
final int historicalX = (int)me.getHistoricalX(pointerIndex, h);
final int historicalY = (int)me.getHistoricalY(pointerIndex, h);
final long historicalTime = me.getHistoricalEventTime(h);
onGestureMoveEvent(historicalX, historicalY, historicalTime,
false /* isMajorEvent */, null);
}
}
if (isShowingMoreKeysPanel()) {
final int translatedX = mMoreKeysPanel.translateX(x);
final int translatedY = mMoreKeysPanel.translateY(y);
mMoreKeysPanel.onMoveEvent(translatedX, translatedY, mPointerId, eventTime);
onMoveKey(x, y);
if (mIsInSlidingKeyInput) {
sDrawingProxy.showSlidingKeyInputPreview(this);
}
return;
}
onMoveEventInternal(x, y, eventTime);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
float eventX = event.getX();
float eventY = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
path.moveTo(eventX, eventY);
lastTouchX = eventX;
lastTouchY = eventY;
// There is no end point yet, so don't waste cycles invalidating.
return true;
case MotionEvent.ACTION_MOVE:
case MotionEvent.ACTION_UP:
// Start tracking the dirty region.
resetDirtyRect(eventX, eventY);
// When the hardware tracks events faster than they are delivered, the
// event will contain a history of those skipped points.
int historySize = event.getHistorySize();
for (int i = 0; i < historySize; i++) {
float historicalX = event.getHistoricalX(i);
float historicalY = event.getHistoricalY(i);
expandDirtyRect(historicalX, historicalY);
path.lineTo(historicalX, historicalY);
}
// After replaying history, connect the line to the touch point.
path.lineTo(eventX, eventY);
break;
default:
Logs.d("Ignored touch event: " + event.toString());
return false;
}
// Include half the stroke width to avoid clipping.
invalidate(
(int) (dirtyRect.left - HALF_STROKE_WIDTH),
(int) (dirtyRect.top - HALF_STROKE_WIDTH),
(int) (dirtyRect.right + HALF_STROKE_WIDTH),
(int) (dirtyRect.bottom + HALF_STROKE_WIDTH));
lastTouchX = eventX;
lastTouchY = eventY;
return true;
}
/** Process incoming touch events */
public boolean onTouchEvent(MotionEvent event) {
try {
int pointerCount = multiTouchSupported ? (Integer) m_getPointerCount.invoke(event) : 1;
if (DEBUG)
Log.i("MultiTouch", "Got here 1 - " + multiTouchSupported + " " + mMode + " " + handleSingleTouchEvents + " " + pointerCount);
if (mMode == MODE_NOTHING && !handleSingleTouchEvents && pointerCount == 1)
// Not handling initial single touch events, just pass them on
return false;
if (DEBUG)
Log.i("MultiTouch", "Got here 2");
// Handle history first (we sometimes get history with ACTION_MOVE events)
int action = event.getAction();
int histLen = event.getHistorySize() / pointerCount;
for (int histIdx = 0; histIdx <= histLen; histIdx++) {
// Read from history entries until histIdx == histLen, then read from current event
boolean processingHist = histIdx < histLen;
if (!multiTouchSupported || pointerCount == 1) {
// Use single-pointer methods -- these are needed as a special case (for some weird reason) even if
// multitouch is supported but there's only one touch point down currently -- event.getX(0) etc. throw
// an exception if there's only one point down.
if (DEBUG)
Log.i("MultiTouch", "Got here 3");
xVals[0] = processingHist ? event.getHistoricalX(histIdx) : event.getX();
yVals[0] = processingHist ? event.getHistoricalY(histIdx) : event.getY();
pressureVals[0] = processingHist ? event.getHistoricalPressure(histIdx) : event.getPressure();
} else {
// Read x, y and pressure of each pointer
if (DEBUG)
Log.i("MultiTouch", "Got here 4");
int numPointers = Math.min(pointerCount, MAX_TOUCH_POINTS);
if (DEBUG && pointerCount > MAX_TOUCH_POINTS)
Log.i("MultiTouch", "Got more pointers than MAX_TOUCH_POINTS");
for (int ptrIdx = 0; ptrIdx < numPointers; ptrIdx++) {
int ptrId = (Integer) m_getPointerId.invoke(event, ptrIdx);
pointerIds[ptrIdx] = ptrId;
// N.B. if pointerCount == 1, then the following methods throw an array index out of range exception,
// and the code above is therefore required not just for Android 1.5/1.6 but also for when there is
// only one touch point on the screen -- pointlessly inconsistent :(
xVals[ptrIdx] = (Float) (processingHist ? m_getHistoricalX.invoke(event, ptrIdx, histIdx) : m_getX.invoke(event, ptrIdx));
yVals[ptrIdx] = (Float) (processingHist ? m_getHistoricalY.invoke(event, ptrIdx, histIdx) : m_getY.invoke(event, ptrIdx));
pressureVals[ptrIdx] = (Float) (processingHist ? m_getHistoricalPressure.invoke(event, ptrIdx, histIdx) : m_getPressure
.invoke(event, ptrIdx));
}
}
// Decode event
decodeTouchEvent(pointerCount, xVals, yVals, pressureVals, pointerIds, //
/* action = */processingHist ? MotionEvent.ACTION_MOVE : action, //
/* down = */processingHist ? true : action != MotionEvent.ACTION_UP //
&& (action & ((1 << ACTION_POINTER_INDEX_SHIFT) - 1)) != ACTION_POINTER_UP //
&& action != MotionEvent.ACTION_CANCEL, //
processingHist ? event.getHistoricalEventTime(histIdx) : event.getEventTime());
}
return true;
} catch (Exception e) {
// In case any of the introspection stuff fails (it shouldn't)
Log.e("MultiTouchController", "onTouchEvent() failed", e);
return false;
}
}
private void handleActionMove(MotionEvent event) {
// Handle all recent motion events so we don't skip any cells even when the device
// is busy...
final float radius = mPathWidth;
final int historySize = event.getHistorySize();
mTmpInvalidateRect.setEmpty();
boolean invalidateNow = false;
for (int i = 0; i < historySize + 1; i++) {
final float x = i < historySize ? event.getHistoricalX(i) : event.getX();
final float y = i < historySize ? event.getHistoricalY(i) : event.getY();
Cell hitCell = detectAndAddHit(x, y);
final int patternSize = mPattern.size();
if (hitCell != null && patternSize == 1) {
mPatternInProgress = true;
notifyPatternStarted();
}
// note current x and y for rubber banding of in progress patterns
final float dx = Math.abs(x - mInProgressX);
final float dy = Math.abs(y - mInProgressY);
if (dx > DRAG_THRESHHOLD || dy > DRAG_THRESHHOLD) {
invalidateNow = true;
}
if (mPatternInProgress && patternSize > 0) {
final ArrayList<Cell> pattern = mPattern;
final Cell lastCell = pattern.get(patternSize - 1);
float lastCellCenterX = getCenterXForColumn(lastCell.column);
float lastCellCenterY = getCenterYForRow(lastCell.row);
// Adjust for drawn segment from last cell to (x,y). Radius accounts for line width.
float left = Math.min(lastCellCenterX, x) - radius;
float right = Math.max(lastCellCenterX, x) + radius;
float top = Math.min(lastCellCenterY, y) - radius;
float bottom = Math.max(lastCellCenterY, y) + radius;
// Invalidate between the pattern's new cell and the pattern's previous cell
if (hitCell != null) {
final float width = mSquareWidth * 0.5f;
final float height = mSquareHeight * 0.5f;
final float hitCellCenterX = getCenterXForColumn(hitCell.column);
final float hitCellCenterY = getCenterYForRow(hitCell.row);
left = Math.min(hitCellCenterX - width, left);
right = Math.max(hitCellCenterX + width, right);
top = Math.min(hitCellCenterY - height, top);
bottom = Math.max(hitCellCenterY + height, bottom);
}
// Invalidate between the pattern's last cell and the previous location
mTmpInvalidateRect.union(Math.round(left), Math.round(top),
Math.round(right), Math.round(bottom));
}
}
mInProgressX = event.getX();
mInProgressY = event.getY();
// To save updates, we only invalidate if the user moved beyond a certain amount.
if (invalidateNow) {
mInvalidate.union(mTmpInvalidateRect);
invalidate(mInvalidate);
mInvalidate.set(mTmpInvalidateRect);
}
}
private boolean considerMoved(MotionEvent event) {
return (sliderRunnable.moved = sliderRunnable.moved || event.getHistorySize() >= 1 && Math.abs(event.getX() - event.getHistoricalX(0)) > 30f);
}