zoukankan      html  css  js  c++  java
  • Android 自定义View手写签名并保存图片

        GIF压缩有问题,运行很顺滑!!!

     

     1.自定义View——支持设置画笔颜色,画笔宽度,画板颜色,清除画板,检查是否有签名,保存画板图片(复制粘贴可直接使用)

    /**
     * Created by YyyyQ on 2020/3/5.
     * 电子签名
     */
    public class SignatureView extends View {
    
        private Context context;
        //X轴起点
        private float x;
        //Y轴起点
        private float y;
        //画笔
        private final Paint paint = new Paint();
        //路径
        private final Path path = new Path();
        //画布
        private Canvas canvas;
        //生成的图片
        private Bitmap bitmap;
        //画笔的宽度
        private int paintWidth = 10;
        //签名颜色
        private int paintColor = Color.BLACK;
        //背景颜色
        private int backgroundColor = Color.WHITE;
        //是否已经签名
        private boolean isTouched = false;
    
        //签名开始与结束
        public interface Touch {
            void OnTouch(boolean isTouch);
        }
    
        private Touch touch;
    
    
        public SignatureView(Context context) {
            super(context);
            init(context);
        }
    
        public SignatureView(Context context, @Nullable AttributeSet attrs) {
            super(context, attrs);
            init(context);
        }
    
        public SignatureView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            init(context);
        }
    
        private void init(Context context) {
            this.context = context;
            //抗锯齿
            paint.setAntiAlias(true);
            //样式
            paint.setStyle(Paint.Style.STROKE);
            //画笔颜色
            paint.setColor(paintColor);
            //画笔宽度
            paint.setStrokeWidth(paintWidth);
        }
    
        @Override
        protected void onSizeChanged(int w, int h, int oldw, int oldh) {
            super.onSizeChanged(w, h, oldw, oldh);
            //创建于view大小一致的bitmap
            bitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
            canvas = new Canvas(bitmap);
            canvas.drawColor(backgroundColor);
            isTouched = false;
        }
    
    
        @Override
        public boolean onTouchEvent(MotionEvent event) {
            if (touch != null) touch.OnTouch(true);
            switch (event.getAction()) {
                //手指按下
                case MotionEvent.ACTION_DOWN:
                    touchDwon(event);
                    break;
                //手指移动
                case MotionEvent.ACTION_MOVE:
                    isTouched = true;
                    if (touch != null) touch.OnTouch(false);
                    touchMove(event);
                    break;
                //手指抬起
                case MotionEvent.ACTION_UP:
                    canvas.drawPath(path, paint);
                    path.reset();
                    break;
            }
            // 更新绘制
            invalidate();
            return true;
        }
    
        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            //画此次笔画之前的签名
            canvas.drawBitmap(bitmap, 0, 0, paint);
            // 通过画布绘制多点形成的图形
            canvas.drawPath(path, paint);
        }
    
    
        //手指按下的方法
        private void touchDwon(MotionEvent event) {
            //重置绘制路径
            path.reset();
            float downX = event.getX();
            float downY = event.getY();
            x = downX;
            y = downY;
            //绘制起点
            path.moveTo(downX, downY);
        }
    
        //手指滑动的方法
        private void touchMove(MotionEvent event) {
            //当前的x,y坐标点
            final float moveX = event.getX();
            final float moveY = event.getY();
            //之前的x,y坐标点
            final float previousX = x;
            final float previousY = y;
            //获取绝对值
            final float dx = Math.abs(moveX - previousX);
            final float dy = Math.abs(moveY - previousY);
            if (dx >= 3 || dy >= 3) {
                float cX = (moveX + previousX) / 2;
                float cY = (moveY + previousY) / 2;
                path.quadTo(previousX, previousY, cX, cY);
                x = moveX;
                y = moveY;
            }
        }
    
        /**
         * 设置画笔颜色
         *
         * @param paintColor
         */
        public void setPaintColor(int paintColor) {
            this.paintColor = paintColor;
            paint.setColor(paintColor);
        }
    
        /**
         * 设置画笔宽度
         *
         * @param paintWidth
         */
        public void setPaintWidth(int paintWidth) {
            this.paintWidth = paintWidth;
            paint.setStrokeWidth(paintWidth);
        }
    
        /**
         * 设置画板颜色
         *
         * @param canvasColor
         */
        public void setCanvasColor(int canvasColor) {
            this.backgroundColor = canvasColor;
        }
    
    
        /**
         * 清除画板
         */
        public void clear() {
            if (canvas != null) {
                isTouched = false;
                //更新画板
                paint.setColor(paintColor);
                paint.setStrokeWidth(paintWidth);
                canvas.drawColor(backgroundColor, PorterDuff.Mode.CLEAR);
                invalidate();
            }
        }
    
        /**
         * 获取画板的Bitmap
         *
         * @return
         */
        public Bitmap getBitmap() {
            setDrawingCacheEnabled(true);
            buildDrawingCache();
            Bitmap bitmap = getDrawingCache();
            setDrawingCacheEnabled(false);
            return bitmap;
        }
    
        /**
         * 是否有签名
         *
         * @return
         */
        public Boolean getSigstatus() {
            return isTouched;
        }
    
        /**
         * 保存画板
         *
         * @param path 保存到路径
         */
        @SuppressLint("WrongThread")
        public Boolean save(String path) throws IOException {
            Bitmap bitmap = this.bitmap;
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            bitmap.compress(Bitmap.CompressFormat.PNG, 100, bos);
            byte[] buffer = bos.toByteArray();
            if (buffer != null) {
                File file = new File(path);
                if (file.exists()) {
                    file.delete();
                }
                OutputStream outputStream = new FileOutputStream(file);
                outputStream.write(buffer);
                outputStream.close();
                return true;
            } else {
                return false;
            }
        }
    
    
    }

     2.xml布局引用自定义View(注意包名)

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
    
        <!--自定义view的绝对路径-->
        <com.example.customviewdemo.view.SignatureView
            android:id="@+id/signature"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:background="#fff" />
    
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:layout_margin="20dp"
            android:orientation="horizontal">
    
            <Button
                android:id="@+id/clear"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:gravity="center"
                android:text="清除" />
    
            <Button
                android:id="@+id/isSignature"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_marginLeft="10dp"
                android:layout_weight="1"
                android:gravity="center"
                android:text="是否签名" />
    
            <Button
                android:id="@+id/save"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_marginLeft="10dp"
                android:layout_weight="1"
                android:gravity="center"
                android:text="保存" />
    
        </LinearLayout>
    
    </LinearLayout>

    3.Activity调用

    /**
    * Created by YyyyQ on 2020/3/9.
    */
    public class SignatureActivity extends AppCompatActivity {


    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_signature);
    SignatureView signatureView = findViewById(R.id.signature);
    //设置画笔颜色(可以不设置--默认画笔宽度10,画笔颜色黑,背景颜色白)
    signatureView.setPaintColor(Color.BLACK);
    signatureView.setPaintWidth(20);
    signatureView.setCanvasColor(Color.WHITE);
    //清除
    Button clear = findViewById(R.id.clear);
    clear.setOnClickListener(view -> {
    signatureView.clear();
    //设置画笔颜色(可以不设置--默认画笔宽度10,画笔颜色黑,背景颜色白)
    signatureView.setPaintColor(Color.BLACK);
    signatureView.setPaintWidth(20);
    signatureView.setCanvasColor(Color.WHITE);
    });
    //是否含有签名
    Button isSignature = findViewById(R.id.isSignature);
    isSignature.setOnClickListener(view -> {
    if (signatureView.getSigstatus()) {
    Toast.makeText(SignatureActivity.this, "有签名", Toast.LENGTH_SHORT).show();
    } else {
    Toast.makeText(SignatureActivity.this, "无签名", Toast.LENGTH_SHORT).show();
    }
    });
    //保存
    Button save = findViewById(R.id.save);
    save.setOnClickListener(view -> {
    try {
    if (signatureView.save("/sdcard/YyyyQ.png")) {
    Toast.makeText(SignatureActivity.this, "保存成功", Toast.LENGTH_SHORT).show();
    } else {
    Toast.makeText(SignatureActivity.this, "保存失败", Toast.LENGTH_SHORT).show();
    }

    } catch (IOException e) {
    e.printStackTrace();
    }

    });

    }
    }

     

  • 相关阅读:
    事物
    性能优化
    eclipse中如何查看一个android模拟器的内部文件
    Android无线测试之—UiAutomator UiDevice API介绍二
    Android无线测试之—UiAutomator UiDevice API介绍一
    Linux最大打开文件描述符数
    Android无线测试之—UiAutmator运行命令介绍与快速调试
    Android无线测试之—UiAutomator编译与运行测试代码
    Android无线测试之—Genymotion配置过程中常见问题
    Android无线测试之—Genymotion模拟器环境搭建
  • 原文地址:https://www.cnblogs.com/YyyyQ/p/12529799.html
Copyright © 2011-2022 走看看