Android 自定义View手写签名

Android 自定义View:手写签名

最近项目中有个新的需求,就是要实现用户手写签名,然后展示再上传到服务器。看到效果图后,先是面对百度编程搜了一下,很多实现方法,主要就是自定义View实现的,为了记录其中的坑,并提升自己的自定义View的能力,还是写出来记录一下。

主要代码如下(用的Kotlin写的):



import android.content.Context
import android.graphics.*
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View
import java.io.ByteArrayOutputStream
import java.io.File
import java.io.FileOutputStream
import java.io.IOException

/**
 * Created by yuan7016 on 2019/07/02. 
* desc : 签名View */ class SignView : View { /** * 画笔 */ private var paint : Paint? = null private var path : Path? = null private lateinit var cacheCanvas : Canvas /** * 签名画布 */ private lateinit var signBitmap: Bitmap //画笔颜色 private var paintColor : Int = Color.BLACK //画笔宽度 private var paintWidth = 15f private var xAlixs : Float = 0.0f private var yAlixs : Float = 0.0f /** * 背景色(指最终签名结果文件的背景颜色,这里我设置为白色) * 你也可以设置为透明的 */ private var mBackColor = Color.WHITE //是否已经签名 private var isSigned : Boolean = false constructor(context: Context?) : super(context){ init(context) } constructor(context: Context?,attributeSet: AttributeSet?) : super(context,attributeSet){ init(context) } constructor(context: Context?,attributeSet: AttributeSet,defStyleAttr : Int) : super(context,attributeSet,defStyleAttr){ init(context) } fun init(context: Context?){ paint = Paint() path = Path() //setBackgroundColor(Color.WHITE) paint?.color = paintColor//设置签名颜色 paint?.style = Paint.Style.STROKE //设置填充样式 paint?.isAntiAlias = true //抗锯齿功能 paint?.strokeWidth = paintWidth//设置画笔宽度 } override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) { super.onSizeChanged(w, h, oldw, oldh) //创建跟view一样大的bitmap,用来保存签名 signBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888) cacheCanvas = Canvas(signBitmap) cacheCanvas.drawColor(mBackColor) isSigned = false } override fun onDraw(canvas: Canvas) { super.onDraw(canvas) //画此次笔画之前的签名 canvas.drawBitmap(signBitmap, 0f, 0f, paint) // 通过画布绘制多点形成的图形 canvas.drawPath(path,paint) } override fun onTouchEvent(event: MotionEvent): Boolean { //记录每次 X , Y轴的坐标 xAlixs = event.x yAlixs = event.y when (event.action) { MotionEvent.ACTION_DOWN -> { path?.reset() path?.moveTo(xAlixs, yAlixs) } MotionEvent.ACTION_MOVE -> { path?.lineTo(xAlixs, yAlixs) isSigned = true } MotionEvent.ACTION_UP -> { //将路径画到bitmap中,即一次笔画完成才去更新bitmap,而手势轨迹是实时显示在画板上的。 cacheCanvas.drawPath(path, paint) path?.reset() } else -> AppLog.e("otherwise") } // 更新绘制 invalidate() return true } /** * 清除画板 */ public fun clear(){ isSigned = false path?.reset() paint?.color = paintColor cacheCanvas.drawColor(mBackColor, PorterDuff.Mode.CLEAR) invalidate() } /** * 保存画板 * * @param path 保存到路径 */ @Throws(IOException::class) fun save(path: String) { val bitmap = signBitmap // 如果图片过大的话,需要压缩图片,不过在我测试手机上最大才50多kb val bos = ByteArrayOutputStream() bitmap.compress(Bitmap.CompressFormat.PNG, 100, bos) val buffer = bos.toByteArray() if (buffer != null) { val file = File(path) if (file.exists()) { file.delete() } val outputStream = FileOutputStream(file) outputStream.write(buffer) outputStream.close() } } //TODO 这里可以扩展一些setter方法 /** * 是否有签名 * * @return isSigned */ public fun getHasSigned() : Boolean{ return isSigned } }

在布局中引用:

    


        


        


    

 

在Activity中保存签名:

 /**
     * 保存签名
     */
    private fun saveSignBitmap(){
        //保存路径
        val path : String = getExternalFilesDir(Environment.DIRECTORY_PICTURES).path + File.separator + "order_sign_" + System.currentTimeMillis() + ".png"

        if (signView.getHasSigned()){
            try {

                signView.save(path)
                ToastUtil.showToast("保存成功!")
                SharedPreferencesUtil.setPreferStr(AppConstant.KEY_SIGN_PATH,path)

                finish()
            }catch ( ex: Exception){
                ToastUtil.showToast("签名保存失败!")
            }

        }else{
            ToastUtil.showToast("您还没有签名,请签名!")
        }

    }

  主要代码及逻辑如上所示。

  效果图如下:

Android 自定义View手写签名_第1张图片

 

你可能感兴趣的:(android自定义View,Android自定义View,手写签名)