Mój kod jest w zasadzie z tego przykładu (http://corner.squareup.com/2010/07/smooth-signatures.html) i Google API (FingerPaint), ale teraz chcę użyć klasy VelocityTracker
w celu zmiany szerokości obrysu w zależności od prędkości mojego palec.Jak narysować ścieżkę o zmiennej szerokości skoku
Pomyślałem, że mogę podzielić ścieżkę na mniejsze części, ale nie znalazłem żadnych przykładów. Jest też ten drugi wpis (http://corner.squareup.com/2012/07/smoother-signatures.html), ale nie mam żadnej konkretnej klasy krzywej Beziera ani nie zbieram wszystkich punktów w ArrayList
, więc ich przykład regulacji szerokości skoku nie jest bardzo pomocny.
Czy ktoś ma pomysł, jak sobie z tym poradzić? Zacząłem uczyć się kodu dwa tygodnie temu, więc jestem całkiem nowy w tym wszystkim.
Edytuj: Próbowałem zaimplementować prędkość moich MotionEvents i użyłem LogCat do śledzenia aktualnej prędkości podczas uruchamiania aplikacji. To się udało, ale kiedy próbowałem użyć prędkości jako części parametru dla mPaint.setStrokeWidth, nie dostałem tego, co faktycznie chciałem. Szerokość ścieżki, którą rysuję na moim płótnie, cały czas się zmieniała od momentu, w którym zacząłem rysować linię, aż przesunąłem palec w górę. Dlatego właśnie chciałbym podzielić ścieżkę na mniejsze części, ponieważ tak jak obecnie, tylko ostatnia śledzona prędkość wpływa na szerokość skoku.
public class SignatureView extends View {
private static final String TAG = SignatureView.class.getSimpleName();
private static final float STROKE_WIDTH = 10;
private static final float HALF_STROKE_WIDTH = STROKE_WIDTH/2;
private final double TOUCH_TOLERANCE = 5;
private int h = getResources().getDisplayMetrics().heightPixels;
private int w = getResources().getDisplayMetrics().widthPixels;
private Path mPath = new Path();
private Paint mPaint = new Paint();
private Paint mBitmapPaint = new Paint(Paint.DITHER_FLAG);
private Bitmap mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
private Canvas mCanvas = new Canvas(mBitmap);
private float mX, mY;
private float lastTouchX, lastTouchY;
private final RectF dirtyRect = new RectF();
public SignatureView(Context context, AttributeSet attrs) {
super(context, attrs);
mPaint.setAntiAlias(true);
mPaint.setColor(Color.BLACK);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeWidth(INITIAL_STROKE_WIDTH);
Log.d(TAG, "TOUCH_TOLERANCE = " +TOUCH_TOLERANCE);
}
@Override
protected void onDraw(Canvas canvas) {
canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
canvas.drawPath(mPath, mPaint);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
float eventX = event.getX();
float eventY = event.getY();
int historySize = event.getHistorySize();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
resetDirtyRect(eventX, eventY);
mPath.reset();
mPath.moveTo(eventX, eventY);
mX = eventX;
mY = eventY;
break;
case MotionEvent.ACTION_MOVE:
float dx = Math.abs(eventX - mX);
float dy = Math.abs(eventY - mY);
if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
mPath.quadTo(mX, mY, (eventX + mX)/2, (eventY + mY)/2);
mX = eventX;
mY = eventY;
}
for (int i = 0; i < historySize; i++) {
float historicalX = event.getHistoricalX(i);
float historicalY = event.getHistoricalY(i);
expandDirtyRect(historicalX, historicalY);
}
break;
case MotionEvent.ACTION_UP:
for (int i = 0; i < historySize; i++) {
float historicalX = event.getHistoricalX(i);
float historicalY = event.getHistoricalY(i);
expandDirtyRect(historicalX, historicalY);
}
mPath.lineTo(mX, mY);
mCanvas.drawPath(mPath, mPaint);
mPath.reset();
break;
default:
Log.d(TAG, "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;
}
private void expandDirtyRect(float historicalX, float historicalY) {
if (historicalX < dirtyRect.left) {
dirtyRect.left = historicalX;
} else if (historicalX > dirtyRect.right) {
dirtyRect.right = historicalX;
}
if (historicalY < dirtyRect.top) {
dirtyRect.top = historicalY;
} else if (historicalY > dirtyRect.bottom) {
dirtyRect.bottom = historicalY;
}
}
private void resetDirtyRect(float eventX, float eventY) {
dirtyRect.left = Math.min(lastTouchX, eventX);
dirtyRect.right = Math.max(lastTouchX, eventX);
dirtyRect.top = Math.min(lastTouchY, eventY);
dirtyRect.bottom = Math.max(lastTouchY, eventY);
}
}
Udało się zmienić szerokość obrysu w zależności od prędkości mojego palca. W rzeczywistości mam ten sam problem w moim kodzie, ale nie jestem w stanie go jeszcze rozwiązać. – AndroidDev