日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > Android >内容正文

Android

android 手写签批_Android自定义实现手写签名功能

發(fā)布時間:2023/12/20 Android 45 豆豆
生活随笔 收集整理的這篇文章主要介紹了 android 手写签批_Android自定义实现手写签名功能 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

一、Android自定義View步驟 :

自定義屬性;

選擇和設(shè)置構(gòu)造方法;

重寫onMeasure()方法;

重寫onDraw()方法;

重寫onLayout()方法;

重寫其他事件的方法(滑動監(jiān)聽等)。

二、代碼實現(xiàn)

工具類代碼:

package com.smt.saveviewtocream.utils;

import android.content.Context;

import android.graphics.Bitmap;

import android.graphics.Canvas;

import android.graphics.Color;

import android.graphics.Paint;

import android.graphics.Path;

import android.graphics.PorterDuff;

import android.util.AttributeSet;

import android.view.MotionEvent;

import android.view.View;

import androidx.annotation.ColorInt;

import java.io.ByteArrayOutputStream;

import java.io.File;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.OutputStream;

/**

* 描述: Android自定義實現(xiàn)手寫簽名功能

*/

public class LinePathView extends View {

private Context mContext;

/**

* 筆畫X坐標起點

*/

private float mX;

/**

* 筆畫Y坐標起點

*/

private float mY;

/**

* 手寫畫筆

*/

private final Paint mGesturePaint = new Paint();

/**

* 路徑

*/

private final Path mPath = new Path();

/**

* 簽名畫筆

*/

private Canvas cacheCanvas;

/**

* 簽名畫布

*/

private Bitmap cachebBitmap;

/**

* 是否已經(jīng)簽名

*/

private boolean isTouched = false;

/**

* 畫筆寬度 px;

*/

private int mPaintWidth = 10;

/**

* 前景色

*/

private int mPenColor = Color.BLACK;

/**

* 背景色(指最終簽名結(jié)果文件的背景顏色,默認為透明色)

*/

private int mBackColor = Color.TRANSPARENT;

//簽名開始與結(jié)束

private Touch touch;

public LinePathView(Context context) {

super(context);

init(context);

}

public LinePathView(Context context, AttributeSet attrs) {

super(context, attrs);

init(context);

}

public LinePathView(Context context, AttributeSet attrs, int defStyleAttr) {

super(context, attrs, defStyleAttr);

init(context);

}

public void init(Context context) {

this.mContext = context;

//設(shè)置抗鋸齒

mGesturePaint.setAntiAlias(true);

//設(shè)置簽名筆畫樣式

mGesturePaint.setStyle(Paint.Style.STROKE);

//設(shè)置筆畫寬度

mGesturePaint.setStrokeWidth(mPaintWidth);

//設(shè)置簽名顏色

mGesturePaint.setColor(mPenColor);

}

@Override

protected void onSizeChanged(int w, int h, int oldw, int oldh) {

super.onSizeChanged(w, h, oldw, oldh);

//創(chuàng)建跟view一樣大的bitmap,用來保存簽名

cachebBitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);

cacheCanvas = new Canvas(cachebBitmap);

cacheCanvas.drawColor(mBackColor);

isTouched = false;

}

@Override

public boolean onTouchEvent(MotionEvent event) {

if (touch != null) touch.OnTouch(true);

switch (event.getAction()) {

case MotionEvent.ACTION_DOWN:

touchDown(event);

break;

case MotionEvent.ACTION_MOVE:

isTouched = true;

if (touch != null) touch.OnTouch(false);

touchMove(event);

break;

case MotionEvent.ACTION_UP:

//將路徑畫到bitmap中,即一次筆畫完成才去更新bitmap,而手勢軌跡是實時顯示在畫板上的。

cacheCanvas.drawPath(mPath, mGesturePaint);

mPath.reset();

break;

}

// 更新繪制

invalidate();

return true;

}

@Override

protected void onDraw(Canvas canvas) {

super.onDraw(canvas);

//畫此次筆畫之前的簽名

canvas.drawBitmap(cachebBitmap, 0, 0, mGesturePaint);

// 通過畫布繪制多點形成的圖形

canvas.drawPath(mPath, mGesturePaint);

}

// 手指點下屏幕時調(diào)用

private void touchDown(MotionEvent event) {

// 重置繪制路線

mPath.reset();

float x = event.getX();

float y = event.getY();

mX = x;

mY = y;

// mPath繪制的繪制起點

mPath.moveTo(x, y);

}

// 手指在屏幕上滑動時調(diào)用

private void touchMove(MotionEvent event) {

final float x = event.getX();

final float y = event.getY();

final float previousX = mX;

final float previousY = mY;

final float dx = Math.abs(x - previousX);

final float dy = Math.abs(y - previousY);

// 兩點之間的距離大于等于3時,生成貝塞爾繪制曲線

if (dx >= 3 || dy >= 3) {

// 設(shè)置貝塞爾曲線的操作點為起點和終點的一半

float cX = (x + previousX) / 2;

float cY = (y + previousY) / 2;

// 二次貝塞爾,實現(xiàn)平滑曲線;previousX, previousY為操作點,cX, cY為終點

mPath.quadTo(previousX, previousY, cX, cY);

// 第二次執(zhí)行時,第一次結(jié)束調(diào)用的坐標值將作為第二次調(diào)用的初始坐標值

mX = x;

mY = y;

}

}

/**

* 清除畫板

*/

public void clear() {

if (cacheCanvas != null) {

isTouched = false;

//更新畫板信息

mGesturePaint.setColor(mPenColor);

cacheCanvas.drawColor(mBackColor, PorterDuff.Mode.CLEAR);

mGesturePaint.setColor(mPenColor);

invalidate();

}

}

public interface Touch {

void OnTouch(boolean isTouch);

}

public Touch getTouch() {

return touch;

}

public void setTouch(Touch touch) {

this.touch = touch;

}

/**

* 保存畫板

*

* @param path 保存到路徑

*/

public void save(String path) throws IOException {

save(path, false, 0);

}

/**

* 保存畫板

*

* @param path 保存到路徑

* @param clearBlank 是否清除邊緣空白區(qū)域

* @param blank 要保留的邊緣空白距離

*/

public void save(String path, boolean clearBlank, int blank) throws IOException {

Bitmap bitmap = cachebBitmap;

//BitmapUtil.createScaledBitmapByHeight(srcBitmap, 300);// 壓縮圖片

if (clearBlank) {

bitmap = clearBlank(bitmap, blank);

}

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

}

}

/**

* 獲取畫板的bitmap

*

* @return

*/

public Bitmap getBitMap() {

setDrawingCacheEnabled(true);

buildDrawingCache();

Bitmap bitmap = getDrawingCache();

setDrawingCacheEnabled(false);

return bitmap;

}

/**

* 逐行掃描 清楚邊界空白。

*

* @param bp

* @param blank 邊距留多少個像素

* @return

*/

private Bitmap clearBlank(Bitmap bp, int blank) {

int HEIGHT = bp.getHeight();

int WIDTH = bp.getWidth();

int top = 0, left = 0, right = 0, bottom = 0;

int[] pixs = new int[WIDTH];

boolean isStop;

//掃描上邊距不等于背景顏色的第一個點

for (int y = 0; y < HEIGHT; y++) {

bp.getPixels(pixs, 0, WIDTH, 0, y, WIDTH, 1);

isStop = false;

for (int pix : pixs) {

if (pix != mBackColor) {

top = y;

isStop = true;

break;

}

}

if (isStop) {

break;

}

}

//掃描下邊距不等于背景顏色的第一個點

for (int y = HEIGHT - 1; y >= 0; y--) {

bp.getPixels(pixs, 0, WIDTH, 0, y, WIDTH, 1);

isStop = false;

for (int pix : pixs) {

if (pix != mBackColor) {

bottom = y;

isStop = true;

break;

}

}

if (isStop) {

break;

}

}

pixs = new int[HEIGHT];

//掃描左邊距不等于背景顏色的第一個點

for (int x = 0; x < WIDTH; x++) {

bp.getPixels(pixs, 0, 1, x, 0, 1, HEIGHT);

isStop = false;

for (int pix : pixs) {

if (pix != mBackColor) {

left = x;

isStop = true;

break;

}

}

if (isStop) {

break;

}

}

//掃描右邊距不等于背景顏色的第一個點

for (int x = WIDTH - 1; x > 0; x--) {

bp.getPixels(pixs, 0, 1, x, 0, 1, HEIGHT);

isStop = false;

for (int pix : pixs) {

if (pix != mBackColor) {

right = x;

isStop = true;

break;

}

}

if (isStop) {

break;

}

}

if (blank < 0) {

blank = 0;

}

//計算加上保留空白距離之后的圖像大小

left = left - blank > 0 ? left - blank : 0;

top = top - blank > 0 ? top - blank : 0;

right = right + blank > WIDTH - 1 ? WIDTH - 1 : right + blank;

bottom = bottom + blank > HEIGHT - 1 ? HEIGHT - 1 : bottom + blank;

return Bitmap.createBitmap(bp, left, top, right - left, bottom - top);

}

/**

* 設(shè)置畫筆寬度 默認寬度為10px

*

* @param mPaintWidth

*/

public void setPaintWidth(int mPaintWidth) {

mPaintWidth = mPaintWidth > 0 ? mPaintWidth : 10;

this.mPaintWidth = mPaintWidth;

mGesturePaint.setStrokeWidth(mPaintWidth);

}

public void setBackColor(@ColorInt int backColor) {

mBackColor = backColor;

}

/**

* 設(shè)置畫筆顏色

*

* @param mPenColor

*/

public void setPenColor(int mPenColor) {

this.mPenColor = mPenColor;

mGesturePaint.setColor(mPenColor);

}

/**

* 是否有簽名

*

* @return

*/

public boolean getTouched() {

return isTouched;

}

}

三、功能實現(xiàn)

layout_main.xml:

android:layout_width="match_parent"

android:layout_height="match_parent"

android:background="@android:color/white"

android:fitsSystemWindows="true"

android:orientation="vertical">

android:id="@+id/mPathView"

android:layout_width="match_parent"

android:layout_height="0dp"

android:layout_weight="1"

android:background="#FFFFFF" />

android:layout_width="match_parent"

android:layout_height="@dimen/qb_px_60"

android:orientation="horizontal">

android:id="@+id/mBtnClear"

android:layout_width="wrap_content"

android:layout_height="match_parent"

android:layout_weight="1"

android:text="清除" />

android:id="@+id/mBtnSave"

android:layout_width="wrap_content"

android:layout_height="match_parent"

android:layout_weight="1"

android:text="保存" />

Maintivity.kt:

import android.graphics.Color

import android.os.Bundle

import android.widget.Toast

import androidx.appcompat.app.AppCompatActivity

import com.smt.saveviewtocream.R

import kotlinx.android.synthetic.main.activity_font_siaze.*

import java.io.IOException

class MainActivity : AppCompatActivity() {

override fun onCreate(savedInstanceState: Bundle?) {

super.onCreate(savedInstanceState)

setContentView(R.layout.activity_font_siaze)

//修改背景、筆寬、顏色

mPathView.setBackColor(Color.WHITE)

mPathView.setPaintWidth(20)

mPathView.setPenColor(Color.BLACK)

mPathView.clear()

//清除

mBtnClear.setOnClickListener {

mPathView.clear()

mPathView.setBackColor(Color.WHITE)

mPathView.setPaintWidth(20)

mPathView.setPenColor(Color.BLACK)

}

//保存

mBtnSave.setOnClickListener {

if (mPathView.touched) {

try {

mPathView.save("/sdcard/qm.png", true, 10)

setResult(100)

Toast.makeText(this@MainActivity, "保存成功~", Toast.LENGTH_SHORT).show()

} catch (e: IOException) {

e.printStackTrace()

}

} else {

Toast.makeText(this@MainActivity, "您沒有簽名~", Toast.LENGTH_SHORT).show()

}

}

}

}

權(quán)限:

總結(jié)

以上是生活随笔為你收集整理的android 手写签批_Android自定义实现手写签名功能的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。