我使用以下代码行在Canvas上绘制路径,到目前为止一切正常,我可以使用此代码轻松绘制路径。
但是现在我们的要求是绘制具有可变宽度的路径,意味着用户绘制的路径基于用户施加的压力,我的意思是说如果用户施加轻压,路径将变薄并且如果用户应用高压路径会很厚等等。到目前为止,我成功地绘制了具有可变宽度的路径,但绘制的线条并不平滑。为什么会发生这种情况,这是我在代码中遗漏的任何内容
帮我简短一点。
我用于绘制具有一个宽度的路径的代码
public class FingerPaint extends GraphicsActivity
{
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(new MyView(this));
}
public void colorChanged(int color)
{
}
public class MyView extends View
{
private static final float STROKE_WIDTH = 5f;
private Paint paint = new Paint();
private Path mPath = new Path();
ArrayList<Path> mPaths = new ArrayList<Path>();
ArrayList<Integer> mStrokes = new ArrayList<Integer>();
private float lastTouchX;
private float lastTouchY;
private final RectF dirtyRect = new RectF();
private int lastStroke = -1;
int variableWidthDelta = 0;
private float mX, mY;
private static final float TOUCH_TOLERANCE = 4;
public MyView(Context context)
{
super(context);
paint.setAntiAlias(true);
paint.setDither(true);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeJoin(Paint.Join.ROUND);
paint.setStrokeCap(Paint.Cap.ROUND);
paint.setStrokeWidth(STROKE_WIDTH);
}
public void clear()
{
mPath.reset();
// Repaints the entire view.
invalidate();
}
@Override
protected void onDraw(Canvas canvas)
{
for(int i=0; i<mPaths.size();i++)
{
paint.setStrokeWidth(mStrokes.get(i));
canvas.drawPath(mPaths.get(i), paint);
}
}
@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:
{
if (event.getPressure()>=0.00 && event.getPressure()<0.05)
{
variableWidthDelta = -2;
}
else if (event.getPressure()>=0.05 && event.getPressure()<0.10)
{
variableWidthDelta = -2;
}
else if (event.getPressure()>=0.10 && event.getPressure()<0.15)
{
variableWidthDelta = -2;
}
else if (event.getPressure()>=0.15 && event.getPressure()<0.20)
{
variableWidthDelta = -2;
}
else if (event.getPressure()>=0.20 && event.getPressure()<0.25)
{
variableWidthDelta = -2;
}
else if (event.getPressure() >= 0.25 && event.getPressure()<0.30)
{
variableWidthDelta = 1;
}
else if (event.getPressure() >= 0.30 && event.getPressure()<0.35)
{
variableWidthDelta = 2;
}
else if (event.getPressure() >= 0.35 && event.getPressure()<0.40)
{
variableWidthDelta = 3;
}
else if (event.getPressure() >= 0.40 && event.getPressure()<0.45)
{
variableWidthDelta = 4;
}
else if (event.getPressure() >= 0.45 && event.getPressure()<0.60)
{
variableWidthDelta = 5;
}
float dx = Math.abs(eventX - mX);
float dy = Math.abs(eventY - mY);
if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE)
{
if(lastStroke != variableWidthDelta)
{
mPath.lineTo(mX, mY);
mPath = new Path();
mPath.moveTo(mX,mY);
mPaths.add(mPath);
mStrokes.add(variableWidthDelta);
}
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);
break;
}
}
// Include half the stroke width to avoid clipping.
invalidate();
lastTouchX = eventX;
lastTouchY = eventY;
lastStroke = variableWidthDelta;
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;
}
}
/**
* Resets the dirty region when the motion event occurs.
*/
private void resetDirtyRect(float eventX, float eventY)
{
// The lastTouchX and lastTouchY were set when the ACTION_DOWN
// motion event occurred.
dirtyRect.left = Math.min(lastTouchX, eventX);
dirtyRect.right = Math.max(lastTouchX, eventX);
dirtyRect.top = Math.min(lastTouchY, eventY);
dirtyRect.bottom = Math.max(lastTouchY, eventY);
}
}
}
答案 0 :(得分:1)
您可以使用getPressure()
方法并将其与此回答https://stackoverflow.com/a/15533607/1112882结合使用,以使其有效。想法是保持存储宽度并使用它。
答案 1 :(得分:1)
我刚发现这个链接。可能它会帮助你。尝试实现它。看来这就是你想要的。
http://www.blogosfera.co.uk/2013/03/how-to-draw-a-path-with-variable-stroke-width/
对于管理统一绘制路径,请检查以下链接:
Android How to draw a smooth line following your finger
希望这会有所帮助。
答案 2 :(得分:0)
更新:感谢Raghunandan和M-WaJeEh。
我错了。你可以参考这个问题。
评论部分的其他链接。
http://developer.android.com/reference/android/view/MotionEvent.html#getPressure(int)
答案 3 :(得分:0)
路径不支持可变宽度绘图。
您可以使用MotionEvent.getPressure()和VelocityTracker.computeCurrentVelocity()方法获得触摸压力和速度。
接下来,您需要创建一个函数,将特定的速度或压力映射到一定的宽度。
假设您准备好这些,绘制可变宽度路径的一种方法是将路径划分为多个路径,每个路径具有不同的宽度。例如,如果宽度需要在单个路径的过程中从10进展到50,则可以有10个路径而不是宽度5,10,15,20 ...依此类推。您将不得不进行大量优化,因为创建大量Path对象将导致内存消耗。
另一种方法是使用quad-curves或bezier curves。
答案 4 :(得分:0)
@Override
protected synchronized void onDraw(Canvas canvas) {
super.onDraw(canvas);
this.canvas = canvas;
Log.d("tag", "Padding" + padding);
int newPadding = (int) padding;
// Set Min X
int xPadding = (int) padding;
Paint bottomLeftTextPaint = new Paint();
Typeface tf = Typeface.create("Helvetica", Typeface.NORMAL);
bottomLeftTextPaint.setColor(context.getResources().getColor(
R.color.common_color_rangeseekbar_bottomtext));
bottomLeftTextPaint.setTextAlign(Align.LEFT);
bottomLeftTextPaint.setTypeface(tf);
bottomLeftTextPaint.setTextSize(20);
bottomLeftTextPaint.setColor(context.getResources().getColor(
R.color.common_color_rangeseekbar_bottomtext));
canvas.drawText(absoluteMinValue + "", newPadding - 5,
0.5f * (getHeight() + lineHeight) + 30, bottomLeftTextPaint);
// draw seek bar background line
final RectF rect = new RectF(newPadding - 5,
0.5f * (getHeight() - lineHeight), getWidth() - padding,
0.5f * (getHeight() + lineHeight));
paint.setStyle(Style.FILL);
// paint.setColor(Color.parseColor("#ED797F"));
paint.setColor(Color.parseColor("#e2e2e2"));
paint.setAntiAlias(true);
canvas.drawRect(rect, paint);
RectF rectStartLine = new RectF(newPadding - 5,
0.5f * (getHeight() - lineHeight) - 5, padding,
0.5f * (getHeight() + lineHeight) + 5);
paint.setStyle(Style.FILL);
paint.setColor(Color.BLACK);
paint.setAntiAlias(true);
canvas.drawRect(rectStartLine, paint);
// End Line
// RectF rectEndLine = new RectF(getWidth() - padding,
// 0.5f * (getHeight() - lineHeight) - 5,
// getWidth() - padding + 5, 0.5f * (getHeight() + lineHeight) + 5);
RectF rectEndLine = new RectF(getWidth() - padding,
0.5f * (getHeight() - lineHeight) - 5,
getWidth() - padding + 5, 0.5f * (getHeight() + lineHeight) + 5);
paint.setStyle(Style.FILL);
paint.setColor(Color.BLACK);
paint.setAntiAlias(true);
canvas.drawRect(rectEndLine, paint);
// End Text
// Set Min X
int xEndPadding = (int) padding;
paint.setColor(Color.parseColor(context.getResources().getString(
R.color.common_color_rangeseekbar_bottomtext)));
paint.setTextSize(20);
int max = (Integer) absoluteMaxValue;
String MaxValue = String.valueOf(max);
paint.setColor(Color.parseColor(context.getResources().getString(
R.color.common_color_rangeseekbar_bottomtext)));
Paint bottomTextPaint = new Paint();
bottomTextPaint.setTypeface(tf);
bottomTextPaint.setColor(context.getResources().getColor(
R.color.common_color_rangeseekbar_bottomtext));
bottomTextPaint.setTextAlign(Align.RIGHT);
bottomTextPaint.setTypeface(tf);
bottomTextPaint.setTextSize(20);
// if (MaxValue.length() > 4) {
//
// canvas.drawText(absoluteMaxValue + "", getWidth() - padding - 23,
// 0.5f * (getHeight() + lineHeight) + 30, bottomTextPaint);
// } else if (MaxValue.length() > 3) {
// canvas.drawText(absoluteMaxValue + "", getWidth() - padding - 18,
// 0.5f * (getHeight() + lineHeight) + 30, bottomTextPaint);
// } else if (MaxValue.length() > 2) {
// canvas.drawText(absoluteMaxValue + "", getWidth() - padding - 13,
// 0.5f * (getHeight() + lineHeight) + 30, bottomTextPaint);
// } else {
canvas.drawText(absoluteMaxValue + "", getWidth() - padding,
0.5f * (getHeight() + lineHeight) + 30, bottomTextPaint);
// }
// draw seek bar active range line
rect.left = normalizedToScreen(normalizedMinValue);
rect.right = normalizedToScreen(normalizedMaxValue);
// orange color
paint.setColor(DEFAULT_COLOR);
paint.setTypeface(tf);
canvas.drawRect(rect, paint);
Paint headerPaint = new Paint();
// Set TextSize
headerPaint.setTextSize(20);
headerPaint.setTextAlign(Align.LEFT);
headerPaint.setTypeface(tf);
headerPaint.setColor(Color.parseColor(context.getResources().getString(
R.color.common_color_rangeseekbar_toptext)));
headerPaint.setTextAlign(Align.LEFT);
// draw minimum thumb
drawThumb(normalizedToScreen(normalizedMinValue),
Thumb.MIN.equals(pressedThumb), canvas);
canvas.drawText("" + getSelectedMinValue(),
normalizedToScreen(normalizedMinValue)-5,
(float) ((0.5f * getHeight()) - thumbHalfHeight) - 8,
headerPaint);
// draw maximum thumb
drawThumb(normalizedToScreen(normalizedMaxValue),
Thumb.MAX.equals(pressedThumb), canvas);
// Right TrackText
Paint righText = new Paint();
righText.setTextAlign(Align.RIGHT);
righText.setAntiAlias(true);
righText.setTextSize(20);
righText.setTypeface(tf);
canvas.drawText("" + getSelectedMaxValue(),
normalizedToScreen(normalizedMaxValue),
(float) ((0.5f * getHeight()) - thumbHalfHeight) , righText);
}
答案 5 :(得分:0)
也许this会帮助你,必须自己实施。