android 可变宽度区域,android – 如何绘制具有可变笔触宽度的路径

这篇博客探讨了如何在Android应用中利用VelocityTracker类根据手指移动速度动态调整SignatureView中笔画的宽度。作者分享了现有的代码基础,主要来源于Square的博客和FingerPaint 示例,并表达了想根据手指速度分段处理路径以实现笔画宽度变化的需求。目前遇到的问题是笔画宽度在整个绘制过程中不断变化,直到手指抬起。文章中提供了部分代码片段,包括ACTION_DOWN、ACTION_MOVE和ACTION_UP事件的处理,但作者寻求帮助来完善根据速度分段并改变strokeWidth的实现。

我的代码基本上来自这个例子(

http://corner.squareup.com/2010/07/smooth-signatures.html)和谷歌API(FingerPaint),但现在我想使用VelocityTracker类来改变笔画宽度,这取决于我的手指速度.

我以为我可以将路径分成更小的部分,但我没有找到任何例子.还有第二篇文章(http://corner.squareup.com/2012/07/smoother-signatures.html),但我没有特定的贝塞尔曲线类,也没有收集ArrayList中的所有点,因此调整笔画宽度的示例不是很有用.

有谁知道如何处理这个?两周前我开始学习代码,所以我对这些东西都很新.

编辑:我试图实现我的MotionEvents的速度,我使用LogCat来跟踪运行应用程序时的当前速度.它确实有效,但当我尝试使用速度作为mPaint.setStrokeWidth参数的一部分时,我没有得到我真正想要的东西.我从画布上绘制的路径的宽度从我开始绘制线条的那一刻起一直在变化,直到我将手指向上移动.这就是为什么我想将路径分成更小的部分,因为现在只有最后一个跟踪的速度会影响strokeWidth.

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);

}

}

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值