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();
}

});

}
}

 

 

 

posted @ 2020-03-20 15:33  ~Y~  阅读(2354)  评论(0编辑  收藏  举报