您的位置:首页 > 房产 > 建筑 > 怎样接入互联网_香港vps云服务器_天津seo顾问_天津百度推广排名

怎样接入互联网_香港vps云服务器_天津seo顾问_天津百度推广排名

2024/12/28 12:53:26 来源:https://blog.csdn.net/qq_14876133/article/details/144078111  浏览:    关键词:怎样接入互联网_香港vps云服务器_天津seo顾问_天津百度推广排名
怎样接入互联网_香港vps云服务器_天津seo顾问_天津百度推广排名

文章目录

  • Android 手写签名板
    • 概述
    • 效果
    • 代码实现
    • 源码下载

Android 手写签名板

概述

手写签名板功能,支持图片保存、支持去除空白区域。

效果

在这里插入图片描述

生成图片效果:

在这里插入图片描述在这里插入图片描述

代码实现

定义属性:

<declare-styleable name="SignatureView"><attr name="bgColor" format="color" /><attr name="brushColor" format="color" /><attr name="brushWidth" format="dimension" />
</declare-styleable>

代码:

class SignatureView @JvmOverloads constructor(context: Context,attrs: AttributeSet? = null,defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) {companion object {const val DEFAULT_BG_COLOR = Color.WHITEconst val DEFAULT_BRUSH_COLOR = Color.BLACKconst val DEFAULT_BRUSH_WIDTH = 12F}private var bgColor: Int = DEFAULT_BG_COLORprivate var brushColor: Int = DEFAULT_BRUSH_COLORprivate var brushWidth = DEFAULT_BRUSH_WIDTHprivate val paint = Paint().apply {isAntiAlias = truecolor = brushColorstyle = Paint.Style.STROKEstrokeWidth = brushWidth}private val path = Path()private var touchX: Float = 0Fprivate var touchY: Float = 0Fprivate var isClear = falseinit {val typedArray = context.obtainStyledAttributes(attrs, R.styleable.SignatureView)bgColor = typedArray.getColor(R.styleable.SignatureView_bgColor, DEFAULT_BG_COLOR)brushColor = typedArray.getColor(R.styleable.SignatureView_brushColor, DEFAULT_BRUSH_COLOR)brushWidth =typedArray.getDimension(R.styleable.SignatureView_brushWidth, DEFAULT_BRUSH_WIDTH)typedArray.recycle()paint.apply {color = brushColorstrokeWidth = brushWidth}setBackgroundColor(bgColor)}/*** 保存图片** @param imageDirs 目录* @param imageName 文件名* @param clearBlank 是否清除空白区域* @param blank 边距*/fun save(imageDirs: String, imageName: String, clearBlank: Boolean = false, blank: Int = 0) {if (imageDirs.isEmpty() || imageName.isEmpty()) {return}if (path.isEmpty) {return}var bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)val canvas = Canvas(bitmap)canvas.drawColor(bgColor)canvas.drawPath(path, paint)if (clearBlank) {bitmap = clearBlank(bitmap, blank)}val dir = File(imageDirs)if (!dir.exists())dir.mkdirs()val file = File(dir, imageName)if (file.exists())file.delete()val out = FileOutputStream(file)try {bitmap.compress(Bitmap.CompressFormat.PNG, 100, out)} catch (e: Exception) {e.printStackTrace()} finally {out.close()}}/*** 清除空白区域** @param bitmap 原图* @param blank 保留边距* @return*/private fun clearBlank(bitmap: Bitmap, blank: Int): Bitmap {var space = blankval width = bitmap.widthval height = bitmap.heightvar left = 0var right = 0var top = 0var bottom = 0var pixs = IntArray(width)var isStop = false//扫描上边距不等于背景颜色的第一个点for (i in 0 until height) {bitmap.getPixels(pixs, 0, width, 0, i, width, 1)isStop = falsefor (pix in pixs) {if (pix != bgColor) {top = iisStop = truebreak}}if (isStop) {break}}//扫描下边距不等于背景颜色的第一个点for (i in height - 1 downTo 0) {bitmap.getPixels(pixs, 0, width, 0, i, width, 1)isStop = falsefor (pix in pixs) {if (pix != bgColor) {bottom = iisStop = truebreak}}if (isStop) {break}}pixs = IntArray(height)//扫描左边距不等于背景颜色的第一个点for (x in 0 until width) {bitmap.getPixels(pixs, 0, 1, x, 0, 1, height)isStop = falsefor (pix in pixs) {if (pix != bgColor) {left = xisStop = truebreak}}if (isStop) {break}}//扫描右边距不等于背景颜色的第一个点for (x in width - 1 downTo 1) {bitmap.getPixels(pixs, 0, 1, x, 0, 1, height)isStop = falsefor (pix in pixs) {if (pix != bgColor) {right = xisStop = truebreak}}if (isStop) {break}}if (space < 0) {space = 0}//计算加上保留空白距离之后的图像大小left = Math.max(left - space, 0)top = Math.max(top - space, 0)right = Math.min(right + space, width - 1)bottom = Math.min(bottom + space, height - 1)return Bitmap.createBitmap(bitmap, left, top, right - left, bottom - top)}/*** 清除画板*/fun clear() {isClear = trueinvalidate()}override fun onTouchEvent(event: MotionEvent): Boolean {when (event.action) {MotionEvent.ACTION_DOWN -> {touchX = event.xtouchY = event.ypath.moveTo(touchX, touchY)return true}MotionEvent.ACTION_MOVE -> {val x = event.xval y = event.yLog.e("TAG", "moveX:$x moveY:$y")// 计算滑动时偏移值val dx = Math.abs(x - touchX)val dy = Math.abs(y - touchY)// 偏移值大于3px绘制if (dx >= 3 || dy >= 3) {val cx = (x + touchX) / 2val cy = (y + touchY) / 2path.quadTo(touchX, touchY, cx, cy)touchX = xtouchY = y}invalidate()}}return super.onTouchEvent(event)}override fun onDraw(canvas: Canvas) {super.onDraw(canvas)if (isClear) {canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);canvas.drawColor(bgColor)path.reset()isClear = false} else {if (!path.isEmpty) {canvas.drawPath(path, paint)}}}
}

使用:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"tools:context=".signature.SignatureActivity"><LinearLayoutandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:orientation="horizontal"><Buttonandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:onClick="onSave1"android:text="保存1" /><Buttonandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:onClick="onSave2"android:text="保存2" /><Buttonandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:onClick="onClear"android:text="清除" /></LinearLayout><com.example.widgets.signature.SignatureViewandroid:id="@+id/signature_view"android:layout_width="match_parent"android:layout_height="match_parent"app:bgColor="@color/blue"app:brushColor="@color/red"app:brushWidth="6dp" />
</LinearLayout>
class SignatureActivity : BaseActivity() {private lateinit var signatureView: SignatureViewoverride fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_signature)signatureView = findViewById(R.id.signature_view)}fun onSave1(view: View) {val imageDir = "${this.cacheDir}/signature"val imageName = "${System.currentTimeMillis()}.png"signatureView.save(imageDir, imageName)}fun onSave2(view: View) {val imageDir = "${this.cacheDir}/signature"val imageName = "${System.currentTimeMillis()}.png"signatureView.save(imageDir, imageName, true, 10)}fun onClear(view: View) {signatureView.clear()}
}

源码下载