PointerLocationView.java revision 829778843cf459384841f9f4ecafe862b6228d6e
1829778843cf459384841f9f4ecafe862b6228d6eDianne Hackbornpackage com.android.internal.widget; 290d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn 390d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackbornimport android.content.Context; 490d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackbornimport android.graphics.Canvas; 590d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackbornimport android.graphics.Paint; 690d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackbornimport android.graphics.Paint.FontMetricsInt; 790d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackbornimport android.util.Log; 890d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackbornimport android.view.MotionEvent; 990d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackbornimport android.view.VelocityTracker; 1090d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackbornimport android.view.View; 1190d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackbornimport android.view.ViewConfiguration; 1290d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn 1390d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackbornimport java.util.ArrayList; 1490d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn 1590d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackbornpublic class PointerLocationView extends View { 1690d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn public static class PointerState { 1790d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn private final ArrayList<Float> mXs = new ArrayList<Float>(); 1890d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn private final ArrayList<Float> mYs = new ArrayList<Float>(); 1990d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn private boolean mCurDown; 2090d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn private int mCurX; 2190d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn private int mCurY; 2290d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn private float mCurPressure; 2390d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn private float mCurSize; 2490d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn private int mCurWidth; 2590d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn private VelocityTracker mVelocity; 2690d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } 2790d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn 2890d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn private final ViewConfiguration mVC; 2990d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn private final Paint mTextPaint; 3090d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn private final Paint mTextBackgroundPaint; 3190d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn private final Paint mTextLevelPaint; 3290d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn private final Paint mPaint; 3390d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn private final Paint mTargetPaint; 3490d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn private final Paint mPathPaint; 3590d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn private final FontMetricsInt mTextMetrics = new FontMetricsInt(); 3690d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn private int mHeaderBottom; 3790d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn private boolean mCurDown; 3890d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn private int mCurNumPointers; 3990d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn private int mMaxNumPointers; 4090d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn private final ArrayList<PointerState> mPointers 4190d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn = new ArrayList<PointerState>(); 4290d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn 4390d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn private boolean mPrintCoords = true; 4490d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn 4590d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn public PointerLocationView(Context c) { 4690d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn super(c); 4790d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mVC = ViewConfiguration.get(c); 4890d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mTextPaint = new Paint(); 4990d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mTextPaint.setAntiAlias(true); 5090d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mTextPaint.setTextSize(10 5190d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn * getResources().getDisplayMetrics().density); 5290d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mTextPaint.setARGB(255, 0, 0, 0); 5390d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mTextBackgroundPaint = new Paint(); 5490d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mTextBackgroundPaint.setAntiAlias(false); 5590d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mTextBackgroundPaint.setARGB(128, 255, 255, 255); 5690d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mTextLevelPaint = new Paint(); 5790d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mTextLevelPaint.setAntiAlias(false); 5890d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mTextLevelPaint.setARGB(192, 255, 0, 0); 5990d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mPaint = new Paint(); 6090d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mPaint.setAntiAlias(true); 6190d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mPaint.setARGB(255, 255, 255, 255); 6290d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mPaint.setStyle(Paint.Style.STROKE); 6390d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mPaint.setStrokeWidth(2); 6490d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mTargetPaint = new Paint(); 6590d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mTargetPaint.setAntiAlias(false); 6690d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mTargetPaint.setARGB(255, 0, 0, 192); 6790d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mPathPaint = new Paint(); 6890d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mPathPaint.setAntiAlias(false); 6990d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mPathPaint.setARGB(255, 0, 96, 255); 7090d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mPaint.setStyle(Paint.Style.STROKE); 7190d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mPaint.setStrokeWidth(1); 7290d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn 7390d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn PointerState ps = new PointerState(); 7490d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn ps.mVelocity = VelocityTracker.obtain(); 7590d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mPointers.add(ps); 7690d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } 7790d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn 7890d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn public void setPrintCoords(boolean state) { 7990d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mPrintCoords = state; 8090d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } 8190d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn 8290d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn @Override 8390d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 8490d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn super.onMeasure(widthMeasureSpec, heightMeasureSpec); 8590d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mTextPaint.getFontMetricsInt(mTextMetrics); 8690d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mHeaderBottom = -mTextMetrics.ascent+mTextMetrics.descent+2; 8790d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn if (false) { 8890d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn Log.i("foo", "Metrics: ascent=" + mTextMetrics.ascent 8990d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn + " descent=" + mTextMetrics.descent 9090d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn + " leading=" + mTextMetrics.leading 9190d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn + " top=" + mTextMetrics.top 9290d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn + " bottom=" + mTextMetrics.bottom); 9390d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } 9490d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } 9590d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn 9690d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn @Override 9790d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn protected void onDraw(Canvas canvas) { 9890d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn synchronized (mPointers) { 9990d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn final int w = getWidth(); 10090d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn final int itemW = w/7; 10190d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn final int base = -mTextMetrics.ascent+1; 10290d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn final int bottom = mHeaderBottom; 10390d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn 10490d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn final int NP = mPointers.size(); 10590d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn 10690d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn if (NP > 0) { 10790d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn final PointerState ps = mPointers.get(0); 10890d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn canvas.drawRect(0, 0, itemW-1, bottom,mTextBackgroundPaint); 10990d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn canvas.drawText("P: " + mCurNumPointers + " / " + mMaxNumPointers, 11090d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn 1, base, mTextPaint); 11190d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn 11290d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn final int N = ps.mXs.size(); 11390d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn if ((mCurDown && ps.mCurDown) || N == 0) { 11490d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn canvas.drawRect(itemW, 0, (itemW * 2) - 1, bottom, mTextBackgroundPaint); 11590d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn canvas.drawText("X: " + ps.mCurX, 1 + itemW, base, mTextPaint); 11690d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn canvas.drawRect(itemW * 2, 0, (itemW * 3) - 1, bottom, mTextBackgroundPaint); 11790d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn canvas.drawText("Y: " + ps.mCurY, 1 + itemW * 2, base, mTextPaint); 11890d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } else { 11990d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn float dx = ps.mXs.get(N-1) - ps.mXs.get(0); 12090d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn float dy = ps.mYs.get(N-1) - ps.mYs.get(0); 12190d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn canvas.drawRect(itemW, 0, (itemW * 2) - 1, bottom, 12290d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn Math.abs(dx) < mVC.getScaledTouchSlop() 12390d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn ? mTextBackgroundPaint : mTextLevelPaint); 12490d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn canvas.drawText("dX: " + String.format("%.1f", dx), 1 + itemW, base, mTextPaint); 12590d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn canvas.drawRect(itemW * 2, 0, (itemW * 3) - 1, bottom, 12690d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn Math.abs(dy) < mVC.getScaledTouchSlop() 12790d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn ? mTextBackgroundPaint : mTextLevelPaint); 12890d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn canvas.drawText("dY: " + String.format("%.1f", dy), 1 + itemW * 2, base, mTextPaint); 12990d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } 13090d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn 13190d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn canvas.drawRect(itemW * 3, 0, (itemW * 4) - 1, bottom, mTextBackgroundPaint); 13290d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn int velocity = ps.mVelocity == null ? 0 : (int) (ps.mVelocity.getXVelocity() * 1000); 13390d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn canvas.drawText("Xv: " + velocity, 1 + itemW * 3, base, mTextPaint); 13490d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn 13590d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn canvas.drawRect(itemW * 4, 0, (itemW * 5) - 1, bottom, mTextBackgroundPaint); 13690d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn velocity = ps.mVelocity == null ? 0 : (int) (ps.mVelocity.getYVelocity() * 1000); 13790d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn canvas.drawText("Yv: " + velocity, 1 + itemW * 4, base, mTextPaint); 13890d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn 13990d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn canvas.drawRect(itemW * 5, 0, (itemW * 6) - 1, bottom, mTextBackgroundPaint); 14090d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn canvas.drawRect(itemW * 5, 0, (itemW * 5) + (ps.mCurPressure * itemW) - 1, 14190d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn bottom, mTextLevelPaint); 14290d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn canvas.drawText("Prs: " + String.format("%.2f", ps.mCurPressure), 1 + itemW * 5, 14390d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn base, mTextPaint); 14490d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn 14590d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn canvas.drawRect(itemW * 6, 0, w, bottom, mTextBackgroundPaint); 14690d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn canvas.drawRect(itemW * 6, 0, (itemW * 6) + (ps.mCurSize * itemW) - 1, 14790d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn bottom, mTextLevelPaint); 14890d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn canvas.drawText("Size: " + String.format("%.2f", ps.mCurSize), 1 + itemW * 6, 14990d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn base, mTextPaint); 15090d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } 15190d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn 15290d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn for (int p=0; p<NP; p++) { 15390d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn final PointerState ps = mPointers.get(p); 15490d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn 15590d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn if (mCurDown && ps.mCurDown) { 15690d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn canvas.drawLine(0, (int)ps.mCurY, getWidth(), (int)ps.mCurY, mTargetPaint); 15790d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn canvas.drawLine((int)ps.mCurX, 0, (int)ps.mCurX, getHeight(), mTargetPaint); 15890d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn int pressureLevel = (int)(ps.mCurPressure*255); 15990d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mPaint.setARGB(255, pressureLevel, 128, 255-pressureLevel); 16090d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn canvas.drawPoint(ps.mCurX, ps.mCurY, mPaint); 16190d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn canvas.drawCircle(ps.mCurX, ps.mCurY, ps.mCurWidth, mPaint); 16290d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } 16390d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } 16490d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn 16590d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn for (int p=0; p<NP; p++) { 16690d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn final PointerState ps = mPointers.get(p); 16790d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn 16890d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn final int N = ps.mXs.size(); 16990d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn float lastX=0, lastY=0; 17090d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn boolean haveLast = false; 17190d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn boolean drawn = false; 17290d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mPaint.setARGB(255, 128, 255, 255); 17390d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn for (int i=0; i<N; i++) { 17490d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn float x = ps.mXs.get(i); 17590d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn float y = ps.mYs.get(i); 17690d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn if (Float.isNaN(x)) { 17790d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn haveLast = false; 17890d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn continue; 17990d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } 18090d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn if (haveLast) { 18190d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn canvas.drawLine(lastX, lastY, x, y, mPathPaint); 18290d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn canvas.drawPoint(lastX, lastY, mPaint); 18390d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn drawn = true; 18490d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } 18590d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn lastX = x; 18690d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn lastY = y; 18790d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn haveLast = true; 18890d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } 18990d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn 19090d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn if (drawn) { 19190d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn if (ps.mVelocity != null) { 19290d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mPaint.setARGB(255, 255, 64, 128); 19390d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn float xVel = ps.mVelocity.getXVelocity() * (1000/60); 19490d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn float yVel = ps.mVelocity.getYVelocity() * (1000/60); 19590d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn canvas.drawLine(lastX, lastY, lastX+xVel, lastY+yVel, mPaint); 19690d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } else { 19790d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn canvas.drawPoint(lastX, lastY, mPaint); 19890d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } 19990d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } 20090d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } 20190d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } 20290d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } 20390d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn 20490d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn public void addTouchEvent(MotionEvent event) { 20590d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn synchronized (mPointers) { 20690d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn int action = event.getAction(); 20790d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn 20890d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn //Log.i("Pointer", "Motion: action=0x" + Integer.toHexString(action) 20990d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn // + " pointers=" + event.getPointerCount()); 21090d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn 21190d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn int NP = mPointers.size(); 21290d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn 21390d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn //mRect.set(0, 0, getWidth(), mHeaderBottom+1); 21490d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn //invalidate(mRect); 21590d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn //if (mCurDown) { 21690d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn // mRect.set(mCurX-mCurWidth-3, mCurY-mCurWidth-3, 21790d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn // mCurX+mCurWidth+3, mCurY+mCurWidth+3); 21890d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn //} else { 21990d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn // mRect.setEmpty(); 22090d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn //} 22190d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn if (action == MotionEvent.ACTION_DOWN) { 22290d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn for (int p=0; p<NP; p++) { 22390d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn final PointerState ps = mPointers.get(p); 22490d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn ps.mXs.clear(); 22590d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn ps.mYs.clear(); 22690d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn ps.mVelocity = VelocityTracker.obtain(); 22790d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn ps.mCurDown = false; 22890d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } 22990d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mPointers.get(0).mCurDown = true; 23090d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mMaxNumPointers = 0; 23190d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn if (mPrintCoords) { 23290d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn Log.i("Pointer", "Pointer 1: DOWN"); 23390d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } 23490d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } 23590d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn 23690d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn if ((action&MotionEvent.ACTION_MASK) == MotionEvent.ACTION_POINTER_DOWN) { 237b125dc5599468a09d82751cd76152071ae485afbDianne Hackborn final int index = (action&MotionEvent.ACTION_POINTER_INDEX_MASK) 238b125dc5599468a09d82751cd76152071ae485afbDianne Hackborn >> MotionEvent.ACTION_POINTER_INDEX_SHIFT; 239b125dc5599468a09d82751cd76152071ae485afbDianne Hackborn final int id = event.getPointerId(index); 24090d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn while (NP <= id) { 24190d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn PointerState ps = new PointerState(); 24290d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn ps.mVelocity = VelocityTracker.obtain(); 24390d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mPointers.add(ps); 24490d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn NP++; 24590d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } 24690d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn final PointerState ps = mPointers.get(id); 24790d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn ps.mVelocity = VelocityTracker.obtain(); 24890d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn ps.mCurDown = true; 24990d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn if (mPrintCoords) { 25090d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn Log.i("Pointer", "Pointer " + (id+1) + ": DOWN"); 25190d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } 25290d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } 25390d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn 25490d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn final int NI = event.getPointerCount(); 25590d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn 25690d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mCurDown = action != MotionEvent.ACTION_UP 25790d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn && action != MotionEvent.ACTION_CANCEL; 25890d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mCurNumPointers = mCurDown ? NI : 0; 25990d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn if (mMaxNumPointers < mCurNumPointers) { 26090d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mMaxNumPointers = mCurNumPointers; 26190d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } 26290d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn 26390d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn for (int i=0; i<NI; i++) { 264b125dc5599468a09d82751cd76152071ae485afbDianne Hackborn final int id = event.getPointerId(i); 265b125dc5599468a09d82751cd76152071ae485afbDianne Hackborn final PointerState ps = mPointers.get(id); 26690d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn ps.mVelocity.addMovement(event); 26790d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn ps.mVelocity.computeCurrentVelocity(1); 26890d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn final int N = event.getHistorySize(); 26990d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn for (int j=0; j<N; j++) { 27090d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn if (mPrintCoords) { 271b125dc5599468a09d82751cd76152071ae485afbDianne Hackborn Log.i("Pointer", "Pointer " + (id+1) + ": (" 27290d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn + event.getHistoricalX(i, j) 27390d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn + ", " + event.getHistoricalY(i, j) + ")" 27490d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn + " Prs=" + event.getHistoricalPressure(i, j) 27590d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn + " Size=" + event.getHistoricalSize(i, j)); 27690d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } 27790d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn ps.mXs.add(event.getHistoricalX(i, j)); 27890d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn ps.mYs.add(event.getHistoricalY(i, j)); 27990d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } 28090d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn if (mPrintCoords) { 281b125dc5599468a09d82751cd76152071ae485afbDianne Hackborn Log.i("Pointer", "Pointer " + (id+1) + ": (" 28290d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn + event.getX(i) + ", " + event.getY(i) + ")" 28390d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn + " Prs=" + event.getPressure(i) 28490d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn + " Size=" + event.getSize(i)); 28590d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } 28690d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn ps.mXs.add(event.getX(i)); 28790d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn ps.mYs.add(event.getY(i)); 28890d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn ps.mCurX = (int)event.getX(i); 28990d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn ps.mCurY = (int)event.getY(i); 29090d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn //Log.i("Pointer", "Pointer #" + p + ": (" + ps.mCurX 29190d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn // + "," + ps.mCurY + ")"); 29290d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn ps.mCurPressure = event.getPressure(i); 29390d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn ps.mCurSize = event.getSize(i); 29490d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn ps.mCurWidth = (int)(ps.mCurSize*(getWidth()/3)); 29590d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } 29690d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn 29790d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn if ((action&MotionEvent.ACTION_MASK) == MotionEvent.ACTION_POINTER_UP) { 298b125dc5599468a09d82751cd76152071ae485afbDianne Hackborn final int index = (action&MotionEvent.ACTION_POINTER_INDEX_MASK) 299b125dc5599468a09d82751cd76152071ae485afbDianne Hackborn >> MotionEvent.ACTION_POINTER_INDEX_SHIFT; 300b125dc5599468a09d82751cd76152071ae485afbDianne Hackborn final int id = event.getPointerId(index); 30190d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn final PointerState ps = mPointers.get(id); 30290d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn ps.mXs.add(Float.NaN); 30390d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn ps.mYs.add(Float.NaN); 30490d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn ps.mCurDown = false; 30590d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn if (mPrintCoords) { 30690d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn Log.i("Pointer", "Pointer " + (id+1) + ": UP"); 30790d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } 30890d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } 30990d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn 31090d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn if (action == MotionEvent.ACTION_UP) { 31190d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn for (int i=0; i<NI; i++) { 312b125dc5599468a09d82751cd76152071ae485afbDianne Hackborn final int id = event.getPointerId(i); 313b125dc5599468a09d82751cd76152071ae485afbDianne Hackborn final PointerState ps = mPointers.get(id); 31490d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn if (ps.mCurDown) { 31590d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn ps.mCurDown = false; 31690d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn if (mPrintCoords) { 317b125dc5599468a09d82751cd76152071ae485afbDianne Hackborn Log.i("Pointer", "Pointer " + (id+1) + ": UP"); 31890d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } 31990d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } 32090d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } 32190d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } 32290d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn 32390d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn //if (mCurDown) { 32490d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn // mRect.union(mCurX-mCurWidth-3, mCurY-mCurWidth-3, 32590d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn // mCurX+mCurWidth+3, mCurY+mCurWidth+3); 32690d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn //} 32790d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn //invalidate(mRect); 32890d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn postInvalidate(); 32990d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } 33090d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } 33190d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn 33290d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn @Override 33390d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn public boolean onTouchEvent(MotionEvent event) { 33490d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn addTouchEvent(event); 33590d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn return true; 33690d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } 33790d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn} 338