欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android實現(xiàn)手寫板功能

 更新時間:2022年06月29日 15:23:20   作者:伏輒  
這篇文章主要為大家詳細(xì)介紹了Android實現(xiàn)手寫板功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下

本文實例為大家分享了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手機鬧鐘用法實例

    Android手機鬧鐘用法實例

    這篇文章主要介紹了Android手機鬧鐘用法,以實例形式較為詳細(xì)的分析了Android實現(xiàn)鬧鐘功能的頁面布局及具體功能相關(guān)技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-09-09
  • Android SQLite詳解及示例代碼

    Android SQLite詳解及示例代碼

    本文主要講解Android SQLite,這里對數(shù)據(jù)庫SQLite 做了詳細(xì)的知識資料整理,并附示例代碼和實現(xiàn)效果圖,有需要的小伙伴可以參考下
    2016-08-08
  • Android中實現(xiàn)長按修改ListView對象的內(nèi)容

    Android中實現(xiàn)長按修改ListView對象的內(nèi)容

    這篇文章主要給大家介紹了在Android中實現(xiàn)長按修改ListView對象內(nèi)容的相關(guān)資料,文中給出了完整的示例代碼,相信對大家具有一定的參考價值,需要的朋友們下面來一起看看吧。
    2017-02-02
  • 詳解 android 光線傳感器 light sensor的使用

    詳解 android 光線傳感器 light sensor的使用

    這篇文章主要介紹了詳解 android 光線傳感器 light sensor的使用的相關(guān)資料,需要的朋友可以參考下
    2017-06-06
  • Android冷啟動優(yōu)化的3個小案例分享

    Android冷啟動優(yōu)化的3個小案例分享

    為了提高App的冷啟動耗時,除了在常規(guī)的業(yè)務(wù)側(cè)進(jìn)行耗時代碼優(yōu)化之外,為了進(jìn)一步縮短啟動耗時,需要在純技術(shù)測做一些優(yōu)化探索,本期我們從類預(yù)加載、Retrofit 、ARouter方面進(jìn)行了進(jìn)一步的優(yōu)化,感興趣的同學(xué)跟著小編一起來看看吧
    2023-07-07
  • Android實現(xiàn)面包屑功能的代碼(支持Fragment聯(lián)動)

    Android實現(xiàn)面包屑功能的代碼(支持Fragment聯(lián)動)

    這篇文章主要介紹了Android實現(xiàn)面包屑功能的代碼(支持Fragment聯(lián)動),本文通過實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-05-05
  • 詳解Flutter如何在單個屏幕上實現(xiàn)多個列表

    詳解Flutter如何在單個屏幕上實現(xiàn)多個列表

    這篇文章主要為大家詳細(xì)介紹了Flutter如何在單個屏幕上實現(xiàn)多個列表,這些列表可以水平排列、網(wǎng)格格式、垂直排列,甚至是這些常用布局的組合,感興趣的小伙伴可以了解下
    2023-11-11
  • Android橫豎屏幕切換小結(jié)

    Android橫豎屏幕切換小結(jié)

    這篇文章主要介紹了Android橫豎屏切換小結(jié)的相關(guān)資料,需要的朋友可以參考下
    2016-02-02
  • Android startActivityForResult實例詳解

    Android startActivityForResult實例詳解

    這篇文章主要介紹了Android startActivityForResult實例詳解的相關(guān)資料,需要的朋友可以參考下
    2017-05-05
  • Android實現(xiàn)自定義圓角對話框Dialog的示例代碼

    Android實現(xiàn)自定義圓角對話框Dialog的示例代碼

    項目中多處用到對話框,本篇文章主要介紹了Android實現(xiàn)圓角對話框Dialog的示例代碼,有興趣的可以了解一下。
    2017-03-03

最新評論