PointerLocationView.java revision f8d0f095e34f8d661ca5b7d555d8610272099bff
1f8d0f095e34f8d661ca5b7d555d8610272099bffKenny Root/* 2f8d0f095e34f8d661ca5b7d555d8610272099bffKenny Root * Copyright (C) 2010 The Android Open Source Project 3f8d0f095e34f8d661ca5b7d555d8610272099bffKenny Root * 4f8d0f095e34f8d661ca5b7d555d8610272099bffKenny Root * Licensed under the Apache License, Version 2.0 (the "License"); 5f8d0f095e34f8d661ca5b7d555d8610272099bffKenny Root * you may not use this file except in compliance with the License. 6f8d0f095e34f8d661ca5b7d555d8610272099bffKenny Root * You may obtain a copy of the License at 7f8d0f095e34f8d661ca5b7d555d8610272099bffKenny Root * 8f8d0f095e34f8d661ca5b7d555d8610272099bffKenny Root * http://www.apache.org/licenses/LICENSE-2.0 9f8d0f095e34f8d661ca5b7d555d8610272099bffKenny Root * 10f8d0f095e34f8d661ca5b7d555d8610272099bffKenny Root * Unless required by applicable law or agreed to in writing, software 11f8d0f095e34f8d661ca5b7d555d8610272099bffKenny Root * distributed under the License is distributed on an "AS IS" BASIS, 12f8d0f095e34f8d661ca5b7d555d8610272099bffKenny Root * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f8d0f095e34f8d661ca5b7d555d8610272099bffKenny Root * See the License for the specific language governing permissions and 14f8d0f095e34f8d661ca5b7d555d8610272099bffKenny Root * limitations under the License. 15f8d0f095e34f8d661ca5b7d555d8610272099bffKenny Root */ 16f8d0f095e34f8d661ca5b7d555d8610272099bffKenny Root 17829778843cf459384841f9f4ecafe862b6228d6eDianne Hackbornpackage com.android.internal.widget; 1890d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn 1990d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackbornimport android.content.Context; 2090d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackbornimport android.graphics.Canvas; 2190d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackbornimport android.graphics.Paint; 2290d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackbornimport android.graphics.Paint.FontMetricsInt; 2390d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackbornimport android.util.Log; 2490d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackbornimport android.view.MotionEvent; 2590d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackbornimport android.view.VelocityTracker; 2690d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackbornimport android.view.View; 2790d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackbornimport android.view.ViewConfiguration; 2890d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn 2990d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackbornimport java.util.ArrayList; 3090d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn 3190d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackbornpublic class PointerLocationView extends View { 3290d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn public static class PointerState { 3390d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn private final ArrayList<Float> mXs = new ArrayList<Float>(); 3490d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn private final ArrayList<Float> mYs = new ArrayList<Float>(); 3590d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn private boolean mCurDown; 3690d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn private int mCurX; 3790d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn private int mCurY; 3890d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn private float mCurPressure; 3990d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn private float mCurSize; 4090d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn private int mCurWidth; 4190d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn private VelocityTracker mVelocity; 4290d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } 4390d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn 4490d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn private final ViewConfiguration mVC; 4590d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn private final Paint mTextPaint; 4690d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn private final Paint mTextBackgroundPaint; 4790d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn private final Paint mTextLevelPaint; 4890d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn private final Paint mPaint; 4990d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn private final Paint mTargetPaint; 5090d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn private final Paint mPathPaint; 5190d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn private final FontMetricsInt mTextMetrics = new FontMetricsInt(); 5290d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn private int mHeaderBottom; 5390d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn private boolean mCurDown; 5490d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn private int mCurNumPointers; 5590d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn private int mMaxNumPointers; 5690d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn private final ArrayList<PointerState> mPointers 5790d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn = new ArrayList<PointerState>(); 5890d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn 5990d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn private boolean mPrintCoords = true; 6090d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn 6190d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn public PointerLocationView(Context c) { 6290d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn super(c); 6390d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mVC = ViewConfiguration.get(c); 6490d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mTextPaint = new Paint(); 6590d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mTextPaint.setAntiAlias(true); 6690d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mTextPaint.setTextSize(10 6790d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn * getResources().getDisplayMetrics().density); 6890d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mTextPaint.setARGB(255, 0, 0, 0); 6990d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mTextBackgroundPaint = new Paint(); 7090d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mTextBackgroundPaint.setAntiAlias(false); 7190d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mTextBackgroundPaint.setARGB(128, 255, 255, 255); 7290d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mTextLevelPaint = new Paint(); 7390d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mTextLevelPaint.setAntiAlias(false); 7490d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mTextLevelPaint.setARGB(192, 255, 0, 0); 7590d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mPaint = new Paint(); 7690d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mPaint.setAntiAlias(true); 7790d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mPaint.setARGB(255, 255, 255, 255); 7890d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mPaint.setStyle(Paint.Style.STROKE); 7990d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mPaint.setStrokeWidth(2); 8090d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mTargetPaint = new Paint(); 8190d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mTargetPaint.setAntiAlias(false); 8290d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mTargetPaint.setARGB(255, 0, 0, 192); 8390d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mPathPaint = new Paint(); 8490d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mPathPaint.setAntiAlias(false); 8590d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mPathPaint.setARGB(255, 0, 96, 255); 8690d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mPaint.setStyle(Paint.Style.STROKE); 8790d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mPaint.setStrokeWidth(1); 8890d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn 8990d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn PointerState ps = new PointerState(); 9090d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn ps.mVelocity = VelocityTracker.obtain(); 9190d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mPointers.add(ps); 9290d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } 9390d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn 9490d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn public void setPrintCoords(boolean state) { 9590d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mPrintCoords = state; 9690d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } 9790d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn 9890d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn @Override 9990d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 10090d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn super.onMeasure(widthMeasureSpec, heightMeasureSpec); 10190d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mTextPaint.getFontMetricsInt(mTextMetrics); 10290d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mHeaderBottom = -mTextMetrics.ascent+mTextMetrics.descent+2; 10390d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn if (false) { 10490d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn Log.i("foo", "Metrics: ascent=" + mTextMetrics.ascent 10590d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn + " descent=" + mTextMetrics.descent 10690d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn + " leading=" + mTextMetrics.leading 10790d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn + " top=" + mTextMetrics.top 10890d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn + " bottom=" + mTextMetrics.bottom); 10990d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } 11090d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } 11190d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn 11290d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn @Override 11390d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn protected void onDraw(Canvas canvas) { 11490d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn synchronized (mPointers) { 11590d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn final int w = getWidth(); 11690d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn final int itemW = w/7; 11790d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn final int base = -mTextMetrics.ascent+1; 11890d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn final int bottom = mHeaderBottom; 11990d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn 12090d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn final int NP = mPointers.size(); 12190d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn 12290d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn if (NP > 0) { 12390d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn final PointerState ps = mPointers.get(0); 12490d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn canvas.drawRect(0, 0, itemW-1, bottom,mTextBackgroundPaint); 12590d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn canvas.drawText("P: " + mCurNumPointers + " / " + mMaxNumPointers, 12690d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn 1, base, mTextPaint); 12790d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn 12890d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn final int N = ps.mXs.size(); 12990d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn if ((mCurDown && ps.mCurDown) || N == 0) { 13090d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn canvas.drawRect(itemW, 0, (itemW * 2) - 1, bottom, mTextBackgroundPaint); 13190d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn canvas.drawText("X: " + ps.mCurX, 1 + itemW, base, mTextPaint); 13290d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn canvas.drawRect(itemW * 2, 0, (itemW * 3) - 1, bottom, mTextBackgroundPaint); 13390d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn canvas.drawText("Y: " + ps.mCurY, 1 + itemW * 2, base, mTextPaint); 13490d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } else { 13590d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn float dx = ps.mXs.get(N-1) - ps.mXs.get(0); 13690d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn float dy = ps.mYs.get(N-1) - ps.mYs.get(0); 13790d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn canvas.drawRect(itemW, 0, (itemW * 2) - 1, bottom, 13890d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn Math.abs(dx) < mVC.getScaledTouchSlop() 13990d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn ? mTextBackgroundPaint : mTextLevelPaint); 14090d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn canvas.drawText("dX: " + String.format("%.1f", dx), 1 + itemW, base, mTextPaint); 14190d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn canvas.drawRect(itemW * 2, 0, (itemW * 3) - 1, bottom, 14290d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn Math.abs(dy) < mVC.getScaledTouchSlop() 14390d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn ? mTextBackgroundPaint : mTextLevelPaint); 14490d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn canvas.drawText("dY: " + String.format("%.1f", dy), 1 + itemW * 2, base, mTextPaint); 14590d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } 14690d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn 14790d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn canvas.drawRect(itemW * 3, 0, (itemW * 4) - 1, bottom, mTextBackgroundPaint); 14890d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn int velocity = ps.mVelocity == null ? 0 : (int) (ps.mVelocity.getXVelocity() * 1000); 14990d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn canvas.drawText("Xv: " + velocity, 1 + itemW * 3, base, mTextPaint); 15090d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn 15190d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn canvas.drawRect(itemW * 4, 0, (itemW * 5) - 1, bottom, mTextBackgroundPaint); 15290d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn velocity = ps.mVelocity == null ? 0 : (int) (ps.mVelocity.getYVelocity() * 1000); 15390d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn canvas.drawText("Yv: " + velocity, 1 + itemW * 4, base, mTextPaint); 15490d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn 15590d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn canvas.drawRect(itemW * 5, 0, (itemW * 6) - 1, bottom, mTextBackgroundPaint); 15690d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn canvas.drawRect(itemW * 5, 0, (itemW * 5) + (ps.mCurPressure * itemW) - 1, 15790d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn bottom, mTextLevelPaint); 15890d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn canvas.drawText("Prs: " + String.format("%.2f", ps.mCurPressure), 1 + itemW * 5, 15990d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn base, mTextPaint); 16090d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn 16190d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn canvas.drawRect(itemW * 6, 0, w, bottom, mTextBackgroundPaint); 16290d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn canvas.drawRect(itemW * 6, 0, (itemW * 6) + (ps.mCurSize * itemW) - 1, 16390d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn bottom, mTextLevelPaint); 16490d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn canvas.drawText("Size: " + String.format("%.2f", ps.mCurSize), 1 + itemW * 6, 16590d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn base, mTextPaint); 16690d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } 16790d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn 16890d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn for (int p=0; p<NP; p++) { 16990d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn final PointerState ps = mPointers.get(p); 17090d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn 17190d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn if (mCurDown && ps.mCurDown) { 17290d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn canvas.drawLine(0, (int)ps.mCurY, getWidth(), (int)ps.mCurY, mTargetPaint); 17390d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn canvas.drawLine((int)ps.mCurX, 0, (int)ps.mCurX, getHeight(), mTargetPaint); 17490d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn int pressureLevel = (int)(ps.mCurPressure*255); 17590d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mPaint.setARGB(255, pressureLevel, 128, 255-pressureLevel); 17690d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn canvas.drawPoint(ps.mCurX, ps.mCurY, mPaint); 17790d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn canvas.drawCircle(ps.mCurX, ps.mCurY, ps.mCurWidth, mPaint); 17890d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } 17990d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } 18090d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn 18190d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn for (int p=0; p<NP; p++) { 18290d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn final PointerState ps = mPointers.get(p); 18390d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn 18490d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn final int N = ps.mXs.size(); 18590d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn float lastX=0, lastY=0; 18690d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn boolean haveLast = false; 18790d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn boolean drawn = false; 18890d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mPaint.setARGB(255, 128, 255, 255); 18990d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn for (int i=0; i<N; i++) { 19090d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn float x = ps.mXs.get(i); 19190d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn float y = ps.mYs.get(i); 19290d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn if (Float.isNaN(x)) { 19390d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn haveLast = false; 19490d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn continue; 19590d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } 19690d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn if (haveLast) { 19790d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn canvas.drawLine(lastX, lastY, x, y, mPathPaint); 19890d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn canvas.drawPoint(lastX, lastY, mPaint); 19990d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn drawn = true; 20090d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } 20190d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn lastX = x; 20290d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn lastY = y; 20390d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn haveLast = true; 20490d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } 20590d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn 20690d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn if (drawn) { 20790d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn if (ps.mVelocity != null) { 20890d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mPaint.setARGB(255, 255, 64, 128); 20990d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn float xVel = ps.mVelocity.getXVelocity() * (1000/60); 21090d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn float yVel = ps.mVelocity.getYVelocity() * (1000/60); 21190d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn canvas.drawLine(lastX, lastY, lastX+xVel, lastY+yVel, mPaint); 21290d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } else { 21390d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn canvas.drawPoint(lastX, lastY, mPaint); 21490d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } 21590d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } 21690d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } 21790d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } 21890d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } 21990d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn 22090d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn public void addTouchEvent(MotionEvent event) { 22190d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn synchronized (mPointers) { 22290d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn int action = event.getAction(); 22390d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn 22490d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn //Log.i("Pointer", "Motion: action=0x" + Integer.toHexString(action) 22590d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn // + " pointers=" + event.getPointerCount()); 22690d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn 22790d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn int NP = mPointers.size(); 22890d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn 22990d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn //mRect.set(0, 0, getWidth(), mHeaderBottom+1); 23090d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn //invalidate(mRect); 23190d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn //if (mCurDown) { 23290d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn // mRect.set(mCurX-mCurWidth-3, mCurY-mCurWidth-3, 23390d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn // mCurX+mCurWidth+3, mCurY+mCurWidth+3); 23490d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn //} else { 23590d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn // mRect.setEmpty(); 23690d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn //} 23790d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn if (action == MotionEvent.ACTION_DOWN) { 23890d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn for (int p=0; p<NP; p++) { 23990d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn final PointerState ps = mPointers.get(p); 24090d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn ps.mXs.clear(); 24190d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn ps.mYs.clear(); 24290d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn ps.mVelocity = VelocityTracker.obtain(); 24390d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn ps.mCurDown = false; 24490d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } 24590d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mPointers.get(0).mCurDown = true; 24690d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mMaxNumPointers = 0; 24790d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn if (mPrintCoords) { 24890d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn Log.i("Pointer", "Pointer 1: DOWN"); 24990d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } 25090d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } 25190d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn 25290d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn if ((action&MotionEvent.ACTION_MASK) == MotionEvent.ACTION_POINTER_DOWN) { 253b125dc5599468a09d82751cd76152071ae485afbDianne Hackborn final int index = (action&MotionEvent.ACTION_POINTER_INDEX_MASK) 254b125dc5599468a09d82751cd76152071ae485afbDianne Hackborn >> MotionEvent.ACTION_POINTER_INDEX_SHIFT; 255b125dc5599468a09d82751cd76152071ae485afbDianne Hackborn final int id = event.getPointerId(index); 25690d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn while (NP <= id) { 25790d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn PointerState ps = new PointerState(); 25890d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn ps.mVelocity = VelocityTracker.obtain(); 25990d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mPointers.add(ps); 26090d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn NP++; 26190d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } 26290d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn final PointerState ps = mPointers.get(id); 26390d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn ps.mVelocity = VelocityTracker.obtain(); 26490d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn ps.mCurDown = true; 26590d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn if (mPrintCoords) { 26690d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn Log.i("Pointer", "Pointer " + (id+1) + ": DOWN"); 26790d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } 26890d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } 26990d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn 27090d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn final int NI = event.getPointerCount(); 27190d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn 27290d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mCurDown = action != MotionEvent.ACTION_UP 27390d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn && action != MotionEvent.ACTION_CANCEL; 27490d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mCurNumPointers = mCurDown ? NI : 0; 27590d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn if (mMaxNumPointers < mCurNumPointers) { 27690d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mMaxNumPointers = mCurNumPointers; 27790d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } 27890d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn 27990d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn for (int i=0; i<NI; i++) { 280b125dc5599468a09d82751cd76152071ae485afbDianne Hackborn final int id = event.getPointerId(i); 281b125dc5599468a09d82751cd76152071ae485afbDianne Hackborn final PointerState ps = mPointers.get(id); 28290d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn ps.mVelocity.addMovement(event); 28390d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn ps.mVelocity.computeCurrentVelocity(1); 28490d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn final int N = event.getHistorySize(); 28590d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn for (int j=0; j<N; j++) { 28690d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn if (mPrintCoords) { 287b125dc5599468a09d82751cd76152071ae485afbDianne Hackborn Log.i("Pointer", "Pointer " + (id+1) + ": (" 28890d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn + event.getHistoricalX(i, j) 28990d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn + ", " + event.getHistoricalY(i, j) + ")" 29090d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn + " Prs=" + event.getHistoricalPressure(i, j) 29190d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn + " Size=" + event.getHistoricalSize(i, j)); 29290d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } 29390d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn ps.mXs.add(event.getHistoricalX(i, j)); 29490d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn ps.mYs.add(event.getHistoricalY(i, j)); 29590d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } 29690d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn if (mPrintCoords) { 297b125dc5599468a09d82751cd76152071ae485afbDianne Hackborn Log.i("Pointer", "Pointer " + (id+1) + ": (" 29890d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn + event.getX(i) + ", " + event.getY(i) + ")" 29990d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn + " Prs=" + event.getPressure(i) 30090d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn + " Size=" + event.getSize(i)); 30190d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } 30290d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn ps.mXs.add(event.getX(i)); 30390d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn ps.mYs.add(event.getY(i)); 30490d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn ps.mCurX = (int)event.getX(i); 30590d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn ps.mCurY = (int)event.getY(i); 30690d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn //Log.i("Pointer", "Pointer #" + p + ": (" + ps.mCurX 30790d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn // + "," + ps.mCurY + ")"); 30890d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn ps.mCurPressure = event.getPressure(i); 30990d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn ps.mCurSize = event.getSize(i); 31090d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn ps.mCurWidth = (int)(ps.mCurSize*(getWidth()/3)); 31190d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } 31290d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn 31390d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn if ((action&MotionEvent.ACTION_MASK) == MotionEvent.ACTION_POINTER_UP) { 314b125dc5599468a09d82751cd76152071ae485afbDianne Hackborn final int index = (action&MotionEvent.ACTION_POINTER_INDEX_MASK) 315b125dc5599468a09d82751cd76152071ae485afbDianne Hackborn >> MotionEvent.ACTION_POINTER_INDEX_SHIFT; 316b125dc5599468a09d82751cd76152071ae485afbDianne Hackborn final int id = event.getPointerId(index); 31790d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn final PointerState ps = mPointers.get(id); 31890d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn ps.mXs.add(Float.NaN); 31990d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn ps.mYs.add(Float.NaN); 32090d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn ps.mCurDown = false; 32190d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn if (mPrintCoords) { 32290d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn Log.i("Pointer", "Pointer " + (id+1) + ": UP"); 32390d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } 32490d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } 32590d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn 32690d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn if (action == MotionEvent.ACTION_UP) { 32790d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn for (int i=0; i<NI; i++) { 328b125dc5599468a09d82751cd76152071ae485afbDianne Hackborn final int id = event.getPointerId(i); 329b125dc5599468a09d82751cd76152071ae485afbDianne Hackborn final PointerState ps = mPointers.get(id); 33090d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn if (ps.mCurDown) { 33190d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn ps.mCurDown = false; 33290d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn if (mPrintCoords) { 333b125dc5599468a09d82751cd76152071ae485afbDianne Hackborn Log.i("Pointer", "Pointer " + (id+1) + ": UP"); 33490d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } 33590d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } 33690d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } 33790d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } 33890d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn 33990d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn //if (mCurDown) { 34090d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn // mRect.union(mCurX-mCurWidth-3, mCurY-mCurWidth-3, 34190d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn // mCurX+mCurWidth+3, mCurY+mCurWidth+3); 34290d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn //} 34390d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn //invalidate(mRect); 34490d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn postInvalidate(); 34590d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } 34690d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } 34790d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn 34890d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn @Override 34990d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn public boolean onTouchEvent(MotionEvent event) { 35090d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn addTouchEvent(event); 35190d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn return true; 35290d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } 35390d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn} 354