Android 将签名布局旋转90度,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("您还没有签名,请签名!")

}

}

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

效果图如下:

d8d3ffb05d3e6467f3271bebeda00708.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值