如何使用 canvas drawPath 或 Path 在 Bitmap 上绘画?我尝试了几个教程但失败了

How to paint on Bitmap using canvas drawPath or Path? I tried several tutorials but failed

所以这是我当前使用 canvas drawLine 的代码,我正在尝试将其修改为 drawPath .

我在 Main 中声明的变量 Activity :

ImageView imageResult;
final int RQS_IMAGE1 = 1;

Paint paint;
Uri source;
Bitmap bitmap;
Canvas canvas;
Path path;

我在 On Create 方法中的代码:

       @Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.drawing_board);

    paint = new Paint();
    paint.setStyle(Paint.Style.FILL);
    paint.setColor(Color.WHITE);
    paint.setStrokeWidth(10);

    //result is the ID of imageview
    imageResult = findViewById(R.id.result);

    //The user will select Images on gallery
    Intent intent = new Intent(Intent.ACTION_PICK,
            android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
    startActivityForResult(intent, RQS_IMAGE1);

其中选择的图像传递到 imageResult 变量然后转换为位图,并且该位图将被放置到 canvas :

    @Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    Bitmap tempBitmap;

    if (resultCode == RESULT_OK) {
        switch (requestCode) {
            case RQS_IMAGE1:
                source = data.getData();

                try {
                    //tempBitmap is Immutable bitmap,
                    //cannot be passed to Canvas constructor
                    tempBitmap = BitmapFactory.decodeStream(
                            getContentResolver().openInputStream(source));

                    Bitmap.Config config;
                    if (tempBitmap.getConfig() != null) {
                        config = tempBitmap.getConfig();
                    } else {
                        config = Bitmap.Config.ARGB_8888;
                    }

                    //bitmap is Mutable bitmap
                    bitmap = Bitmap.createBitmap(
                            tempBitmap.getWidth(),
                            tempBitmap.getHeight(),
                            config);

                    canvas = new Canvas(bitmap);
                    canvas.drawBitmap(tempBitmap, 0, 0, null);

                    imageResult.setImageBitmap(bitmap);
                } catch (FileNotFoundException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }

                break;
        }
    }
}

现在,这是我获取用户手指触摸点并将 canvas.drawLine 放入运动事件中的方法。然后,他们可以在放置 Imageview 的 canvas 上绘画:

    private float mX,mY;
public void paintOn_Image(){

imageResult.setOnTouchListener(new View.OnTouchListener() {

    @Override
    public boolean onTouch(View v, MotionEvent event) {

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

        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                mX = x;
                mY = y;
           float ratioWidth = (float)bitmap.getWidth()/(float)v.getWidth();
           float ratioHeight = (float)bitmap.getHeight()/(float)v.getHeight();

                canvas.drawLine(
                        mX * ratioWidth,
                        mY * ratioHeight,
                        x * ratioWidth,
                        y * ratioHeight,
                        paint);

                imageResult.invalidate();
                break;

            case MotionEvent.ACTION_MOVE:

                ratioWidth = (float) bitmap.getWidth() / (float) v.getWidth();
                ratioHeight = (float)bitmap.getHeight()/(float)v.getHeight();

                canvasMaster.drawLine(
                        mX * ratioWidth,
                        mY * ratioHeight,
                        x * ratioWidth,
                        y * ratioHeight,
                        paint);

                imageResult.invalidate();

                mX = x;
                mY = y;
                break;

            case MotionEvent.ACTION_UP:

                ratioWidth = (float) bitmapMaster.getWidth() / (float) v.getWidth();
                ratioHeight = (float)bitmapMaster.getHeight()/(float)v.getHeight();

                canvasMaster.drawLine(
                        x * ratioWidth,
                        y * ratioHeight,
                        x * ratioWidth,
                        y * ratioHeight,
                        paint);

                imageResult.invalidate();
                break;
        }

        return true;
    }
});

这是我到目前为止所做的。 在 motionEvent.ACTION_DOWN、ACTION_MOVE & ACTION_UP 中,我更改为:

                    canvas.drawLine(
                        mX * ratioWidth,
                        mY * ratioHeight,
                        x * ratioWidth,
                        y * ratioHeight,
                        paint);

                imageResult.invalidate();
                break;

进入这个:

                path.moveTo(mX*ratioWidth,mY*ratioHeight);
                path.lineTo(x*ratioWidth,y*ratioHeight);
                path.moveTo(mX*ratioWidth,y*ratioHeight);
                path.lineTo(x*ratioWidth,mY*ratioHeight);
                canvas.drawPath(path,paintDraw);
                imageResult.invalidate();

                canvas.drawPath(path, paint);

                imageResult.invalidate();
                break;

但是当用户触摸 canvas 时应用程序崩溃了:(

如何使用 Path 在 canvas 上绘画?计算是否不正确?

我试图将其更改为路径的原因是我们无法撤消 drawLine画入后canvas。所以如果你有解决方案 undo/clear/remove drawLine,它也适用于我。谢谢。

在阅读了本论坛中的大量文档、教程和信息之后。

只需创建 DrawableView 和 CustomImageview,而不是停留在 Imageview 上。

Sources