【问题标题】:Draw a smooth line and small gradually in android在android中画一条平滑的线逐渐变小
【发布时间】:2014-02-10 11:46:15
【问题描述】:

我正在尝试实现一个简单的可绘制视图。 现在我正在使用Path's quadTo 方法来绘制一条平滑线。

结果如下:

我不知道当用户快速移动手指时如何逐渐画出一条细小的线。与此示例相同:

你知道我怎样才能得到这个结果吗? (任何方式,引擎或开源)。现在,我正在考虑实现我自己的“quadTo”方法。但我认为它会很慢(或者超出我的能力)。因为它是 Android SDK 上的原生方法。

感谢您的帮助。

这是我的简单可绘制视图的实现,供任何需要它的人使用:

public class TestView extends LinearLayout{

private static final String TAG = "TestView";
private PointF previousPoint;
private PointF startPoint;
private PointF currentPoint;
private static final float STROKE_WIDTH = 5f;

private static final float HALF_STROKE_WIDTH = STROKE_WIDTH / 2;

private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
private Paint paintBm = new Paint(Paint.ANTI_ALIAS_FLAG);
private Bitmap bmp;
private Canvas canvasBmp;
private Path path;
private int paintSize = 25;

public TestView(Context context, AttributeSet attrs) {
    super(context, attrs);

    this.setWillNotDraw(false);
    paint.setAntiAlias(true);

    paint.setStyle(Paint.Style.STROKE);
    paint.setStrokeJoin(Paint.Join.ROUND);
    paint.setStrokeCap(Paint.Cap.ROUND);
    paint.setStrokeWidth(STROKE_WIDTH);
    paint.setColor(Color.BLACK);
    //paint.setAlpha(100);

    paintBm.setAntiAlias(true);

    paintBm.setStyle(Paint.Style.STROKE);
    paintBm.setStrokeJoin(Paint.Join.ROUND);
    paintBm.setStrokeCap(Paint.Cap.ROUND);
    paintBm.setStrokeWidth(STROKE_WIDTH);
    paintBm.setColor(Color.BLACK);
    paintBm.setAlpha(100);
    path = new Path();
    //paint.setPathEffect(new CornerPathEffect(2));
}

public TestView(Context context) {
    super(context);
    // TODO Auto-generated constructor stub
    paint.setAntiAlias(true);

    paint.setStyle(Paint.Style.STROKE);
    paint.setStrokeJoin(Paint.Join.ROUND);
    paint.setStrokeCap(Paint.Cap.ROUND);
    paint.setStrokeWidth(STROKE_WIDTH);
    paint.setColor(Color.BLACK);

    path = new Path();
    //paint.setPathEffect(new CornerPathEffect(2));
}



@Override
protected void onLayout(boolean changed, int left, int top, int right,
        int bottom) {
    // TODO Auto-generated method stub
    super.onLayout(changed, left, top, right, bottom);
    if(bmp == null){
        bmp = Bitmap.createBitmap(right-left,bottom-top,Bitmap.Config.ARGB_8888);
        canvasBmp = new Canvas(bmp);

    }
}
@Override
public boolean onTouchEvent(MotionEvent event) {
    //printSamples(event);
    switch (event.getAction()) {
    case MotionEvent.ACTION_DOWN:
        currentPoint = new PointF(event.getX(), event.getY());
        previousPoint = currentPoint;
        startPoint = previousPoint;
        path.reset();
        break;

    case MotionEvent.ACTION_MOVE:
        startPoint = previousPoint;
        previousPoint = currentPoint;
        currentPoint = new PointF(event.getX(), event.getY());
        int historySize = event.getHistorySize();
        for(int i = 0; i < historySize; i++){

        }



        drawLine(canvasBmp, path, paint, previousPoint, currentPoint);
        //path.moveTo(currentPoint.x, currentPoint.y);
        break;
    case MotionEvent.ACTION_UP:
        startPoint = previousPoint;
        previousPoint = currentPoint;
        currentPoint = new PointF(event.getX(), event.getY());
        drawLine(canvasBmp, path, paint, previousPoint, currentPoint);
        paintSize = 25;
        break;
    default:
        break;
    }

    invalidate();
    return true;// super.onTouchEvent(event);
}


@Override
protected void onDraw(Canvas canvas) {
    Log.v("pichan", "dasd");
    //canvas.drawBitmap(bmp, 0,0, null);
    //canvas.drawColor(Color.BLUE);
    //canvas.drawPath(path, paint); 
    canvas.drawBitmap(bmp, 0, 0, paintBm);

}





private void drawLine(Canvas canvas, Path path, Paint paint, PointF start, PointF end)
{
    PointF mid1 = midPoint(previousPoint, startPoint);
    PointF mid2 = midPoint(end, start);

    path.reset();
    paint.setStrokeWidth(paintSize);
    path.moveTo(mid1.x, mid1.y);
    path.quadTo(previousPoint.x, previousPoint.y, mid2.x, mid2.y);
    canvas.drawPath(path, paint);
    //canvas.
    //paintSize -= 1;
}

private PointF  midPoint(PointF p1, PointF p2)
{
    return new PointF((p1.x + p2.x) / 2.0f ,  (p1.y + p2.y) * 0.5f);
}

}

【问题讨论】:

  • 我用你的逻辑来绘制平滑线,是的,它工作得很好,但在我的情况下,路径是使用可变宽度绘制的,为了实现这一点,我检测来自运动事件的压力并基于施加的压力用户直接使用手写笔,我正在更改笔画宽度,使用您的逻辑一切正常,但有时绘制的路径不正确。你能检查一下我的代码有什么问题吗pastebin.com/niDbXf29
  • 这是个好主意,我现在很忙。我会检查它到晚上。希望我能帮忙
  • 好的..没有问题。还要检查屏幕截图。这样您就可以知道我的代码 imageshack.us/photo/my-images/28/4o3t.png 中的实际错误
  • 嗨@Anshuman。我检查了您的解决方案和您的问题。我认为用你的解决方案,这条线不可能是平滑的。因为事件(MotionEvent)之间的距离不同。如果您的手指快速移动,则距离会更长并且反向。示例我们有三个点:p1,p2,p3。 p1-> p2 = 5,笔画大小为10。p2-> p3 = 10,笔画大小为20。=>线条不能平滑。
  • 实际上在我的情况下,基于不同的压力值,我将 strokeWidth 值设置为我的绘画对象,在我的情况下绘制的线条是平滑的,但是当压力值变化时绘制一条线,然后连接点基于压力绘制的细线和粗线之间看起来像是相互重叠的。那么有没有办法解决这个问题。给你发送新的截图,告诉你实际的错误imageshack.com/a/img132/7016/8y0v.png

标签: android android-widget


【解决方案1】:

经过一段时间的研究,我构建了一个SignView,让用户登录或绘图,结果将保存到图像文件中。

有兴趣的可以看看这里: SignView

希望这个自定义视图可以节省一些时间。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多