blob: 4ef97a2113888dad3f4d7216ef24528ff889e25e [file] [log] [blame]
/*
* Copyright (C) 2007 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.development;
import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.Paint.FontMetricsInt;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.WindowManager;
import android.view.VelocityTracker;
import android.view.View;
import java.util.ArrayList;
/**
* Demonstrates wrapping a layout in a ScrollView.
*
*/
public class PointerLocation extends Activity {
@Override
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(new MyView(this));
// Make the screen full bright for this activity.
WindowManager.LayoutParams lp = getWindow().getAttributes();
lp.screenBrightness = 1.0f;
getWindow().setAttributes(lp);
}
public static class PointerState {
private final ArrayList<Float> mXs = new ArrayList<Float>();
private final ArrayList<Float> mYs = new ArrayList<Float>();
private boolean mCurDown;
private int mCurX;
private int mCurY;
private float mCurPressure;
private float mCurSize;
private int mCurWidth;
private VelocityTracker mVelocity;
}
public class MyView extends View {
private final Paint mTextPaint;
private final Paint mTextBackgroundPaint;
private final Paint mTextLevelPaint;
private final Paint mPaint;
private final Paint mTargetPaint;
private final FontMetricsInt mTextMetrics = new FontMetricsInt();
private int mHeaderBottom;
private boolean mCurDown;
private final ArrayList<PointerState> mPointers
= new ArrayList<PointerState>();
public MyView(Context c) {
super(c);
mTextPaint = new Paint();
mTextPaint.setAntiAlias(true);
mTextPaint.setTextSize(10
* getResources().getDisplayMetrics().density);
mTextPaint.setARGB(255, 0, 0, 0);
mTextBackgroundPaint = new Paint();
mTextBackgroundPaint.setAntiAlias(false);
mTextBackgroundPaint.setARGB(128, 255, 255, 255);
mTextLevelPaint = new Paint();
mTextLevelPaint.setAntiAlias(false);
mTextLevelPaint.setARGB(192, 255, 0, 0);
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setARGB(255, 255, 255, 255);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(2);
mTargetPaint = new Paint();
mTargetPaint.setAntiAlias(false);
mTargetPaint.setARGB(192, 0, 0, 255);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(1);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
mTextPaint.getFontMetricsInt(mTextMetrics);
mHeaderBottom = -mTextMetrics.ascent+mTextMetrics.descent+2;
Log.i("foo", "Metrics: ascent=" + mTextMetrics.ascent
+ " descent=" + mTextMetrics.descent
+ " leading=" + mTextMetrics.leading
+ " top=" + mTextMetrics.top
+ " bottom=" + mTextMetrics.bottom);
}
@Override
protected void onDraw(Canvas canvas) {
int w = getWidth()/5;
int base = -mTextMetrics.ascent+1;
int bottom = mHeaderBottom;
final int NP = mPointers.size();
if (NP > 0) {
final PointerState ps = mPointers.get(0);
canvas.drawRect(0, 0, w-1, bottom, mTextBackgroundPaint);
canvas.drawText("X: " + ps.mCurX, 1, base, mTextPaint);
canvas.drawRect(w, 0, (w * 2) - 1, bottom, mTextBackgroundPaint);
canvas.drawText("Y: " + ps.mCurY, 1 + w, base, mTextPaint);
canvas.drawRect(w * 2, 0, (w * 3) - 1, bottom, mTextBackgroundPaint);
canvas.drawRect(w * 2, 0, (w * 2) + (ps.mCurPressure * w) - 1, bottom, mTextLevelPaint);
canvas.drawText("Pres: " + ps.mCurPressure, 1 + w * 2, base, mTextPaint);
canvas.drawRect(w * 3, 0, (w * 4) - 1, bottom, mTextBackgroundPaint);
canvas.drawRect(w * 3, 0, (w * 3) + (ps.mCurSize * w) - 1, bottom, mTextLevelPaint);
canvas.drawText("Size: " + ps.mCurSize, 1 + w * 3, base, mTextPaint);
canvas.drawRect(w * 4, 0, getWidth(), bottom, mTextBackgroundPaint);
int velocity = ps.mVelocity == null ? 0 : (int) (ps.mVelocity.getYVelocity() * 1000);
canvas.drawText("yVel: " + velocity, 1 + w * 4, base, mTextPaint);
}
for (int p=0; p<NP; p++) {
final PointerState ps = mPointers.get(p);
final int N = ps.mXs.size();
float lastX=0, lastY=0;
mPaint.setARGB(255, 0, 255, 255);
for (int i=0; i<N; i++) {
float x = ps.mXs.get(i);
float y = ps.mYs.get(i);
if (i > 0) {
canvas.drawLine(lastX, lastY, x, y, mTargetPaint);
canvas.drawPoint(lastX, lastY, mPaint);
}
lastX = x;
lastY = y;
}
if (ps.mVelocity != null) {
mPaint.setARGB(255, 255, 0, 0);
float xVel = ps.mVelocity.getXVelocity() * (1000/60);
float yVel = ps.mVelocity.getYVelocity() * (1000/60);
canvas.drawLine(lastX, lastY, lastX+xVel, lastY+yVel, mPaint);
} else {
canvas.drawPoint(lastX, lastY, mPaint);
}
}
if (mCurDown && NP > 0) {
final PointerState ps = mPointers.get(0);
canvas.drawLine(0, (int)ps.mCurY, getWidth(), (int)ps.mCurY, mTargetPaint);
canvas.drawLine((int)ps.mCurX, 0, (int)ps.mCurX, getHeight(), mTargetPaint);
int pressureLevel = (int)(ps.mCurPressure*255);
mPaint.setARGB(255, pressureLevel, 128, 255-pressureLevel);
canvas.drawPoint(ps.mCurX, ps.mCurY, mPaint);
canvas.drawCircle(ps.mCurX, ps.mCurY, ps.mCurWidth, mPaint);
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
int action = event.getAction();
//Log.i("Pointer", "Motion: action=0x" + Integer.toHexString(action)
// + " pointers=" + event.getPointerCount());
int NP = mPointers.size();
//mRect.set(0, 0, getWidth(), mHeaderBottom+1);
//invalidate(mRect);
//if (mCurDown) {
// mRect.set(mCurX-mCurWidth-3, mCurY-mCurWidth-3,
// mCurX+mCurWidth+3, mCurY+mCurWidth+3);
//} else {
// mRect.setEmpty();
//}
if (action == MotionEvent.ACTION_DOWN) {
for (int p=0; p<NP; p++) {
final PointerState ps = mPointers.get(p);
ps.mXs.clear();
ps.mYs.clear();
ps.mVelocity = VelocityTracker.obtain();
}
}
while (NP < event.getPointerCount()) {
PointerState ps = new PointerState();
ps.mVelocity = VelocityTracker.obtain();
mPointers.add(ps);
NP++;
}
if ((action&MotionEvent.ACTION_MASK) == MotionEvent.ACTION_POINTER_DOWN) {
final PointerState ps = mPointers.get(
(action&MotionEvent.ACTION_POINTER_MASK)
>> MotionEvent.ACTION_POINTER_SHIFT);
ps.mXs.clear();
ps.mYs.clear();
ps.mVelocity = VelocityTracker.obtain();
}
if (NP > event.getPointerCount()) {
NP = event.getPointerCount();
}
mCurDown = action != MotionEvent.ACTION_UP
&& action != MotionEvent.ACTION_CANCEL;
for (int p=0; p<NP; p++) {
final PointerState ps = mPointers.get(p);
ps.mVelocity.addMovement(event);
ps.mVelocity.computeCurrentVelocity(1);
final int N = event.getHistorySize();
for (int i=0; i<N; i++) {
ps.mXs.add(event.getHistoricalX(p, i));
ps.mYs.add(event.getHistoricalY(p, i));
}
ps.mXs.add(event.getX(p));
ps.mYs.add(event.getY(p));
ps.mCurX = (int)event.getX(p);
ps.mCurY = (int)event.getY(p);
//Log.i("Pointer", "Pointer #" + p + ": (" + ps.mCurX
// + "," + ps.mCurY + ")");
ps.mCurPressure = event.getPressure(p);
ps.mCurSize = event.getSize(p);
ps.mCurWidth = (int)(ps.mCurSize*(getWidth()/3));
}
//if (mCurDown) {
// mRect.union(mCurX-mCurWidth-3, mCurY-mCurWidth-3,
// mCurX+mCurWidth+3, mCurY+mCurWidth+3);
//}
//invalidate(mRect);
invalidate();
return true;
}
}
}