Android實現(xiàn)手寫板功能
本文實例為大家分享了Android實現(xiàn)手寫板功能的具體代碼,供大家參考,具體內(nèi)容如下
自定義個一個手寫板的重點:
筆畫為一次down-move-up的集合
撤銷筆畫并非一次path的動作撤銷 應(yīng)該也是一次down-move -up的撤銷
為了更好的筆畫需要使用貝塞爾曲線來完成
效果如下:

截圖中清楚 的意思是清除 !
具體代碼如下:
package com.kyli.base.view;
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.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import androidx.annotation.Nullable;
import java.util.ArrayList;
import java.util.List;
/**
?* 繪制畫板
?*/
public class SignBoradView extends View {
? ? /*4個像素點*/
? ? private int beierThreshold = 4;
? ? private float x = 0;
? ? private float y = 0;
? ? /*畫筆*/
? ? private Paint mPaint;
? ? /*寬度*/
? ? private int strokeWidth = 10;
? ? /*yanbse*/
? ? private int color = Color.BLACK;
? ? /*當(dāng)前筆畫*/
? ? private Path path;
? ? private int state = State.CLEAR;
? ? private interface State {
? ? ? ? /*畫板可以使用了*/
? ? ? ? int START = 0;
? ? ? ? /*停止使用畫板*/
? ? ? ? int STOP = 1;
? ? ? ? /*清空畫板*/
? ? ? ? int CLEAR = 2;
? ? }
? ? private List<EveryPenPath> everyPenPaths = new ArrayList<>();
? ? /*每一個筆畫*/
? ? private static class EveryPenPath {
? ? ? ? public Path path;
? ? }
? ? public SignBoradView(Context context) {
? ? ? ? super(context);
? ? }
? ? public SignBoradView(Context context, @Nullable AttributeSet attrs) {
? ? ? ? super(context, attrs);
? ? }
? ? public SignBoradView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
? ? ? ? super(context, attrs, defStyleAttr);
? ? }
? ? private void initPaint() {
? ? ? ? if (mPaint == null) {
? ? ? ? ? ? mPaint = new Paint();
? ? ? ? ? ? mPaint.setStrokeWidth(strokeWidth);
? ? ? ? ? ? mPaint.setColor(color);
? ? ? ? ? ? mPaint.setStyle(Paint.Style.STROKE);
? ? ? ? ? ? mPaint.setAntiAlias(true);
? ? ? ? ? ? mPaint.setFlags(Paint.ANTI_ALIAS_FLAG);
? ? ? ? }
? ? }
? ? public void start() {
? ? ? ? state = State.START;
? ? ? ? initPaint();
? ? }
? ? /*停止使用*/
? ? public void stop() {
? ? ? ? state = State.STOP;
? ? }
? ? /*清空畫板*/
? ? public void clear() {
? ? ? ? state = State.CLEAR;
? ? ? ? for (int i = everyPenPaths.size() - 1; i >= 0; i--) {
? ? ? ? ? ? EveryPenPath everyPenPath = everyPenPaths.get(i);
? ? ? ? ? ? everyPenPath.path.reset();
? ? ? ? ? ? everyPenPath.path.close();
? ? ? ? ? ? everyPenPath.path = null;
? ? ? ? }
? ? ? ? everyPenPaths.clear();
? ? ? ? invalidate();
? ? }
? ? public void back() {
? ? ? ? int count = everyPenPaths.size();
? ? ? ? if (count < 1)
? ? ? ? ? ? return;
? ? ? ? EveryPenPath everyPenPath = everyPenPaths.get(count - 1);
? ? ? ? everyPenPath.path.reset();
? ? ? ? everyPenPath.path.close();
? ? ? ? everyPenPath.path = null;
? ? ? ? everyPenPaths.remove(count - 1);
? ? ? ? invalidate();
? ? }
? ? @Override
? ? protected void onDraw(Canvas canvas) {
? ? ? ? super.onDraw(canvas);
? ? ? ? if (state == State.START) {
? ? ? ? ? ? /*先繪制完整筆畫*/
? ? ? ? ? ? for (EveryPenPath e : everyPenPaths) {
? ? ? ? ? ? ? ? canvas.drawPath(e.path, mPaint);
? ? ? ? ? ? }
? ? ? ? ? ? //當(dāng)前進(jìn)行中的 ?path!=null
? ? ? ? ? ? if (path != null) {
? ? ? ? ? ? ? ? canvas.drawPath(path, mPaint);
? ? ? ? ? ? }
? ? ? ? }
? ? }
? ? @Override
? ? public boolean onTouchEvent(MotionEvent event) {
? ? ? ? if (state == State.START) {
? ? ? ? ? ? if (event.getAction() == MotionEvent.ACTION_UP) {
? ? ? ? ? ? ? ? actionUp(event);
? ? ? ? ? ? ? ? invalidate();
? ? ? ? ? ? ? ? return true;
? ? ? ? ? ? }
? ? ? ? ? ? if (event.getAction() == MotionEvent.ACTION_MOVE) {
? ? ? ? ? ? ? ? actionMove(event);
? ? ? ? ? ? ? ? invalidate();
? ? ? ? ? ? ? ? return true;
? ? ? ? ? ? }
? ? ? ? ? ? if (event.getAction() == MotionEvent.ACTION_DOWN) {
? ? ? ? ? ? ? ? actionDown(event);
? ? ? ? ? ? ? ? invalidate();
? ? ? ? ? ? ? ? return true;
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? return super.onTouchEvent(event);
? ? }
? ? private void actionUp(MotionEvent event) {
? ? ? ? actionMove(event);
? ? ? ? /*構(gòu)成一個筆畫*/
? ? ? ? EveryPenPath everyPenPath = new EveryPenPath();
? ? ? ? everyPenPath.path = path;
? ? ? ? everyPenPaths.add(everyPenPath);
? ? ? ? //將當(dāng)前畫筆置位null;
? ? ? ? path = null;
? ? }
? ? /**/
? ? private void actionMove(MotionEvent event) {
? ? ? ? /*每次移動去繪制貝塞爾曲線*/
? ? ? ? float cX = event.getX();
? ? ? ? float cY = event.getY();
? ? ? ? float dX = Math.abs(cX - x);//變化量
? ? ? ? float dY = Math.abs(cY - y);
? ? ? ? if (dX >= beierThreshold || dY >= beierThreshold) {
? ? ? ? ? ? float rX = x + (cX - x) / 2;
? ? ? ? ? ? float rY = y + (cY - y) / 2;
? ? ? ? ? ? path.quadTo(rX, rY, cX, cY);
? ? ? ? ? ? //下次的x 域y 將重新計算
? ? ? ? ? ? x = cX;
? ? ? ? ? ? y = cY;
? ? ? ? }
? ? }
? ? /*開始時*/
? ? private void actionDown(MotionEvent event) {
? ? ? ? path = new Path();
? ? ? ? x = event.getX();
? ? ? ? y = event.getY();
? ? ? ? path.moveTo(x, y);
? ? }
? ? public void setBeierThreshold(int beierThreshold) {
? ? ? ? this.beierThreshold = beierThreshold;
? ? }
? ? public void setStrokeWidth(int strokeWidth) {
? ? ? ? this.strokeWidth = strokeWidth;
? ? }
? ? public void setColor(int color) {
? ? ? ? this.color = color;
? ? }
? ? public Bitmap getResult(int bgColor) {
? ? ? ? if (everyPenPaths.size() == 0)
? ? ? ? ? ? return null;
? ? ? ? Bitmap bitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
? ? ? ? Canvas canvas = new Canvas(bitmap);
? ? ? ? canvas.drawColor(bgColor);
? ? ? ? for (int i = 0; i < everyPenPaths.size(); i++) {
? ? ? ? ? ? if (mPaint == null) {
? ? ? ? ? ? ? ? initPaint();
? ? ? ? ? ? }
? ? ? ? ? ? canvas.drawPath(everyPenPaths.get(i).path, mPaint);
? ? ? ? }
? ? ? ? return bitmap;
? ? }
? ? public Bitmap getResult() {
? ? ? ? return getResult(Color.WHITE);
? ? }
}以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Android自定義Gallery控件實現(xiàn)3D圖片瀏覽器
這篇文章主要介紹了Android自定義Gallery控件實現(xiàn)3D圖片瀏覽器,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-04-04
Android UI實現(xiàn)單行文本水平觸摸滑動效果
這篇文章主要為大家詳細(xì)介紹了Android UI實現(xiàn)單行文本水平觸摸滑動效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2016-10-10
Android自定義View實現(xiàn)進(jìn)度條動畫
這篇文章主要為大家詳細(xì)介紹了Android自定義View實現(xiàn)進(jìn)度條動畫,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-08-08
淺談Android客戶端與服務(wù)器的數(shù)據(jù)交互總結(jié)
這篇文章主要介紹了淺談Android客戶端與服務(wù)器的數(shù)據(jù)交互總結(jié),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-09-09
Android?Flutter實現(xiàn)自由落體彈跳動畫效果
粒子運動是將對象按照一定物理公式進(jìn)行的自定義軌跡運動,與普通動畫不同的是,它沒有強(qiáng)制性的動畫開始到結(jié)束的時間概念。本文將利用Flutter實現(xiàn)自由落體彈跳動畫效果,感興趣的小伙伴可以學(xué)習(xí)一下2022-10-10

