Android Studio 一个简单的涂鸦APP,实现缩放、移动、涂鸦、保存

        最近工作需要研究了一下安卓的涂鸦,实现了单指移动,双指缩放,涂鸦,保存的功能。上代码!

        首先是页面布局,用于显示图片和涂鸦。

    <ImageView
        android:id="@+id/image_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scaleType="matrix" />

    <View
        android:id="@+id/drawing_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:layout_editor_absoluteX="0dp"
        tools:layout_editor_absoluteY="0dp" />

        在onCreate中对页面的view进行实例,并将原始图片显示在imageView中,创建与原始图片大小相匹配的Mutable Bitmap和画布

 imageView = findViewById(R.id.image_view);
        drawingView = findViewById(R.id.drawing_view);

        // 设置触摸事件监听器
        imageView.setOnTouchListener(this);
        drawingView.setOnTouchListener(this);

        // 加载原始图片
        originalBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);

        // 创建与原始图片大小相匹配的Mutable Bitmap
        mutableBitmap = originalBitmap.copy(Bitmap.Config.ARGB_8888, true);
        bitmapBackup0 = originalBitmap.copy(Bitmap.Config.ARGB_8888, true);//打开原始图像时,即备份

        // 创建画布并与Mutable Bitmap关联
        drawingCanvas = new Canvas(mutableBitmap);

初始化画笔

        // 初始化画笔
        paint = new Paint();
        paint.setColor(Color.RED);
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeWidth(5f);
在ImageView中显示原始图片,根据当前视图比例进行变化matrix,使图片完整显示
        imageView.setImageBitmap(originalBitmap);
        img_w = originalBitmap.getWidth();
        img_h = originalBitmap.getHeight();
        Log.d(TAG, "onCreate: img_w = "+img_w+"    img_h = "+img_h);
        view_w = 1080;//视图 宽
        view_h = 2124;//视图 高
//        int view_w = imageView.getWidth();
//        int view_h = imageView.getHeight();
        Log.d(TAG, "onCreate: view_w = "+view_w+"    view_h = "+view_h);

//        if(img_w<img_h)
//        {
        init_ratio = (1080*(1.0f))/(img_w*(1.0f));
        Log.d(TAG, "aaaaaaaaaaaaaaaaaaaaa init_ratio = "+init_ratio);
        matrix.reset();
        matrix.postScale(init_ratio,init_ratio);
        current_disY = 300;//为了不挡住上面的主菜单栏
        matrix.postTranslate(0 ,current_disY);
        imageView.setImageMatrix(matrix);
onTouch处理触摸事件,包括缩放、移动、涂鸦。涂鸦时根据缩放、移动后的X,Y坐标变化而变化,否则会无法根据实际触点画线
@Override
    public boolean onTouch(View v, MotionEvent event) {
        Log.d(TAG, "onTouch: event.getPointerCount() = "+event.getPointerCount());
        Log.d(TAG, "onTouch: event.getAction() = "+event.getAction());
        if (event.getPointerCount() == 2) {
            two_pointer_down = true;
            isDrawLine = false;
            Log.d(TAG, "onTouch: ~~~~~~~~~~~~~~~~~~~~~~~");
            //处理双指缩放
            switch (event.getAction()) {
                case MotionEvent.ACTION_MOVE:
                    if(distance1 ==0)
                    {
                        distance1 = getDistance(event);
                    }
                    current_ratio = getDistance(event)/distance1;
                    Log.d(TAG, "onTouch: distance1 = "+distance1);
                    distance1 = getDistance(event);

                    Log.d(TAG, "onTouch: current_ratio = "+current_ratio);
                    total_ratio = current_ratio*total_ratio;
                    Log.d(TAG, "onTouch: total_ratio = "+total_ratio);

                    float centerX = (event.getX(0)+event.getX(1))/2;
                    float centerY = (event.getY(0)+event.getY(1))/2;
                    Log.d(TAG, "onTouch: centerX = "+centerX);
                    Log.d(TAG, "onTouch: centerY = "+centerY);

//                    disX = centerX/total_ratio;
//                    disY = centerY/total_ratio;

                    matrix.reset();
                    matrix.postScale(init_ratio*total_ratio,init_ratio*total_ratio);
                    float translateX = 0f;
                    float translateY = 0f;
                    translateX = (current_disX*current_ratio)+centerX*(1-current_ratio);
                    translateY = (current_disY*current_ratio)+centerY*(1-current_ratio);
                    Log.d(TAG, "onTouch: translateX = "+translateX);
                    Log.d(TAG, "onTouch: translateY = "+translateY);
                    matrix.postTranslate(translateX, translateY);
//                    matrix.postTranslate((disX+current_disX)+centerX*(total_ratio/2), (disY+current_disY)+centerY*(total_ratio/2));
                    imageView.setImageMatrix(matrix);
//
                    current_disX = translateX;
                    current_disY = translateY;


                    Log.d(TAG, "onTouch: getDistance = "+getDistance(event));
                    break;
                default:
                    break;
            }
        } else if (event.getPointerCount() == 1) {
            if (two_pointer_down == false) {
                if (move == true) {
                    //处理单指移动
                    switch (event.getAction()) {
                        case MotionEvent.ACTION_DOWN:
                            currentX = event.getX();
                            currentY = event.getY();
                            Log.d(TAG, "onTouch: currentX = " + currentX + "   currentY = " + currentY);
                            break;
                        case MotionEvent.ACTION_MOVE:
                            nextX = event.getX();
                            nextY = event.getY();
                            Log.d(TAG, "onTouch: nextX = " + nextX + "   nextY" + nextY);
                            disX = nextX - currentX;
                            disY = nextY - currentY;
                            Log.d(TAG, "onTouch: disX = " + disX + "   disY" + disY);

                            matrix.reset();
                            matrix.postScale(init_ratio * total_ratio, init_ratio * total_ratio);
                            matrix.postTranslate(disX + current_disX, disY + current_disY);
                            imageView.setImageMatrix(matrix);
                            current_disX = disX + current_disX;
                            current_disY = disY + current_disY;

                            currentX = nextX;
                            currentY = nextY;
                            break;
                        default:
                            break;
                    }
                } else {
                    // 处理单指涂鸦
                    switch (event.getAction()) {
                        case MotionEvent.ACTION_DOWN:
                            isDrawLine = true;
                            startPoint.set((event.getX() - current_disX) / (init_ratio * total_ratio), (event.getY() - current_disY) / (init_ratio * total_ratio));
                            break;
                        case MotionEvent.ACTION_MOVE:
                            Log.d(TAG, "onTouch: isDrawLine = true");
                            float x = (event.getX() - current_disX) / (init_ratio * total_ratio);
                            float y = (event.getY() - current_disY) / (init_ratio * total_ratio);
                            drawingCanvas.drawLine(startPoint.x, startPoint.y, x, y, paint);
                            imageView.setImageBitmap(mutableBitmap);
                            startPoint.set(x, y);
                            break;
                        default:
                            break;
                    }
                }
            }
        }
        switch (event.getAction()) {
            case MotionEvent.ACTION_UP:
                distance1 = 0;
                Log.d(TAG, "onTouch: 0 = distance1 = "+distance1);
                if(two_pointer_down == true) {
                    two_pointer_down = false;//当双指触摸都弹起的时候,才能进行单指操作
                }
                if(isDrawLine == true){
                    bitmap_backup(mutableBitmap);
                    isDrawLine = false;
                }
                break;
            default:
                break;

        }
        return true;
    }

获取量触摸点间的距离,用于缩放

    private float getDistance(MotionEvent event) {
        float dx = event.getX(0) - event.getX(1);
        float dy = event.getY(0) - event.getY(1);
        return (float) Math.sqrt(dx * dx + dy * dy);
    }

保存图片,就直接搞个button点击保存即可,调用如下参考代码(保存地址根据实际情况修改,这里添加随机数,防止覆盖之前保存的图片)

private void saveImage() {
        int randomNumber = getRandomNumber(1, 999999);
        save_path = "/storage/emulated/0/DCIM/Doodle/"+"final_image"+randomNumber+".jpg";
        Log.d(TAG, "saveImage: "+save_path);
        FileOutputStream outputStream;
        try {
            outputStream = new FileOutputStream(save_path);
            mutableBitmap.compress(Bitmap.CompressFormat.JPEG, 100, outputStream);
            outputStream.close();
            Toast.makeText(this, "保存成功", Toast.LENGTH_SHORT).show();

            //保存图片后,需要将对应图片插入到图库
            sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(new File(save_path))));

            TextView save_image_position = findViewById(R.id.save_image_position);
            save_image_position.setText("图片位置:"+save_path);
        } catch (IOException e) {
            e.printStackTrace();
            Toast.makeText(this, "保存失败", Toast.LENGTH_SHORT).show();
        }
    }

以上差不多就是涂鸦的全部代码,因为是从整个工程里面抠出来的,可能会有些变量为定义啥的,注意甄别一下。然后需要保存和从手机内存里打开图片需要在Mainfest.xml中添加一下权限,添加了权限也要在手机设置里确认一下app是否有权限访问内存,否则可能会有预期之外的错误发生。

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

本代码GitHub 链接 Android Studio工程,无需拆封,可直接食用https://github.com/0MakkaPakka0/MyDoodleC.git

 之前有一位大佬专门写的涂鸦app,功能特别齐全,体验感俱佳,有github工程。链接如下奉上android图片涂鸦,具有设置画笔,撤销,缩放移动等功能(二)_forward123_的博客-CSDN博客

  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值