为了账号安全,请及时绑定邮箱和手机立即绑定

Android如何用手指画出流畅的线条

/ 猿问

Android如何用手指画出流畅的线条

桃花长相依 2019-08-24 15:16:42

Android如何用手指画出流畅的线条

http://marakana.com/tutorials/android/2d-graphics-example.html

我在下面使用这个例子。但当我在屏幕上移动我的手指太快时,线条会变成单个点。

我不确定我是否可以加快绘图速度。或者我应该用直线连接最后两个点。这两个解决方案中的第二个似乎是一个不错的选择,除非你的手指移动非常快,你将有一条直线的长段然后是尖锐的曲线。

如果有任何其他解决方案,听到它们会很棒。

在此先感谢您的帮助。


查看完整描述

3 回答

?
aluckdog

如上所述,一个简单的解决方案是简单地用直线连接点。这是执行此操作的代码:

public void onDraw(Canvas canvas) {
    Path path = new Path();
    boolean first = true;
    for(Point point : points){
        if(first){
            first = false;
            path.moveTo(point.x, point.y);
        }
        else{
            path.lineTo(point.x, point.y);
        }
    }
    canvas.drawPath(path, paint);}

确保你将油漆从填充变为中风:

paint = new Paint(Paint.ANTI_ALIAS_FLAG);paint.setStyle(Paint.Style.STROKE);paint.setStrokeWidth(2);paint.setColor(Color.WHITE);

另一种选择是使用quadTo方法将点连接到iterpolation:

public void onDraw(Canvas canvas) {
    Path path = new Path();
    boolean first = true;
    for(int i = 0; i < points.size(); i += 2){
        Point point = points.get(i);
        if(first){
            first = false;
            path.moveTo(point.x, point.y);
        }

        else if(i < points.size() - 1){
            Point next = points.get(i + 1);
            path.quadTo(point.x, point.y, next.x, next.y);
        }
        else{
            path.lineTo(point.x, point.y);
        }
    }

    canvas.drawPath(path, paint);}

这仍然会产生一些尖锐的边缘。

如果你真的雄心勃勃,你可以开始计算三次样条曲线,如下所示:

public void onDraw(Canvas canvas) {
    Path path = new Path();

    if(points.size() > 1){
        for(int i = points.size() - 2; i < points.size(); i++){
            if(i >= 0){
                Point point = points.get(i);

                if(i == 0){
                    Point next = points.get(i + 1);
                    point.dx = ((next.x - point.x) / 3);
                    point.dy = ((next.y - point.y) / 3);
                }
                else if(i == points.size() - 1){
                    Point prev = points.get(i - 1);
                    point.dx = ((point.x - prev.x) / 3);
                    point.dy = ((point.y - prev.y) / 3);
                }
                else{
                    Point next = points.get(i + 1);
                    Point prev = points.get(i - 1);
                    point.dx = ((next.x - prev.x) / 3);
                    point.dy = ((next.y - prev.y) / 3);
                }
            }
        }
    }

    boolean first = true;
    for(int i = 0; i < points.size(); i++){
        Point point = points.get(i);
        if(first){
            first = false;
            path.moveTo(point.x, point.y);
        }
        else{
            Point prev = points.get(i - 1);
            path.cubicTo(prev.x + prev.dx, prev.y + prev.dy, point.x - point.dx, point.y - point.dy, point.x, point.y);
        }
    }
    canvas.drawPath(path, paint);}

此外,我发现您需要更改以下内容以避免重复的动作事件:

public boolean onTouch(View view, MotionEvent event) {
    if(event.getAction() != MotionEvent.ACTION_UP){
        Point point = new Point();
        point.x = event.getX();
        point.y = event.getY();
        points.add(point);
        invalidate();
        Log.d(TAG, "point: " + point);
        return true;
    }
    return super.onTouchEvent(event);}

并将dx和dy值添加到Point类:

class Point {
    float x, y;
    float dx, dy;

    @Override
    public String toString() {
        return x + ", " + y;
    }}

这会产生平滑的线条,但有时必须使用循环连接点。此外,对于长绘图会话,这在计算上变得计算密集。

希望有助于...有趣的东西可以玩。

编辑

我汇总了一个展示这些不同技术的快速项目,包括Square的suggessted签名实现。享受:https//github.com/johncarl81/androiddraw


查看完整回答
反对 回复 2019-08-24
?
撒科打诨

这对你来说可能不再那么重要了,但我努力解决它并且我想分享,可能对其他人有用。

提供@johncarl解决方案的教程非常适合绘图,但它们为我的目的提供了限制。如果您将手指从屏幕上移开并将其放回,此解决方案将在最后一次点击和新点击之间画一条线,使整个图形始终连接。所以我试图找到一个解决方案,最后我得到了它!(对不起,如果听起来很明显,我是图形的初学者)

public class MainActivity extends Activity {
    DrawView drawView;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // Set full screen view
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                     WindowManager.LayoutParams.FLAG_FULLSCREEN);
        requestWindowFeature(Window.FEATURE_NO_TITLE);

        drawView = new DrawView(this);
        setContentView(drawView);
        drawView.requestFocus();
    }}public class DrawingPanel extends View implements OnTouchListener {
    private static final String TAG = "DrawView";

    private static final float MINP = 0.25f;
    private static final float MAXP = 0.75f;

    private Canvas  mCanvas;
    private Path    mPath;
    private Paint       mPaint;   
    private LinkedList<Path> paths = new LinkedList<Path>();

    public DrawingPanel(Context context) {
        super(context);
        setFocusable(true);
        setFocusableInTouchMode(true);

        this.setOnTouchListener(this);

        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setDither(true);
        mPaint.setColor(Color.BLACK);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeJoin(Paint.Join.ROUND);
        mPaint.setStrokeCap(Paint.Cap.ROUND);
        mPaint.setStrokeWidth(6);
        mCanvas = new Canvas();
        mPath = new Path();
        paths.add(mPath);
    }               

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
    }

    @Override
    protected void onDraw(Canvas canvas) {            
        for (Path p : paths){
            canvas.drawPath(p, mPaint);
        }
    }

    private float mX, mY;
    private static final float TOUCH_TOLERANCE = 4;

    private void touch_start(float x, float y) {
        mPath.reset();
        mPath.moveTo(x, y);
        mX = x;
        mY = y;
    }

    private void touch_move(float x, float y) {
        float dx = Math.abs(x - mX);
        float dy = Math.abs(y - mY);
        if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
            mPath.quadTo(mX, mY, (x + mX)/2, (y + mY)/2);
            mX = x;
            mY = y;
        }
    }

    private void touch_up() {
        mPath.lineTo(mX, mY);
        // commit the path to our offscreen
        mCanvas.drawPath(mPath, mPaint);
        // kill this so we don't double draw            
        mPath = new Path();
        paths.add(mPath);
    }

    @Override
    public boolean onTouch(View arg0, MotionEvent event) {
        float x = event.getX();
        float y = event.getY();

        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                touch_start(x, y);
                invalidate();
                break;
            case MotionEvent.ACTION_MOVE:
                touch_move(x, y);
                invalidate();
                break;
            case MotionEvent.ACTION_UP:
                touch_up();
                invalidate();
                break;
        }
        return true;
    } }

我用你的手指画了android样本并稍微修改它来存储每个路径而不是最后一个路径!希望它可以帮到某人!

干杯。


查看完整回答
反对 回复 2019-08-24
?
jeck猫

如果你想要它简单:

public class DrawByFingerCanvas extends View {

    private Paint brush = new Paint(Paint.ANTI_ALIAS_FLAG);
    private Path path = new Path();

    public DrawByFingerCanvas(Context context) {
        super(context);
        brush.setStyle(Paint.Style.STROKE);
        brush.setStrokeWidth(5);
    }

    @Override
    protected void onDraw(Canvas c) {
        c.drawPath(path, brush);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {

        float x = event.getX();
        float y = event.getY();

        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                path.moveTo(x,y);
                break;
            case MotionEvent.ACTION_MOVE:
                path.lineTo(x, y);
                break;
            default:
                return false;
        }
        invalidate();
        return true;
    }}

在活动中:

@Overrideprotected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(new DrawByFingerCanvas(this));}

结果:

https://img2.mukewang.com/5d60e4cc00019eb003600640.jpg

要擦除所有图纸,只需旋转屏幕即可。


查看完整回答
反对 回复 2019-08-24

添加回答

回复

举报

0/150
提交
取消
意见反馈 邀请有奖 帮助中心 APP下载
官方微信