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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

Android画板开发(二) 橡皮擦实现

發布時間:2024/3/12 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android画板开发(二) 橡皮擦实现 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Android畫板開發(一) 基本畫筆的實現
Android畫板開發(二) 橡皮擦實現
Android畫板開發(三) 撤銷反撤銷功能實現
Android畫板開發(四) 添加背景和保存畫板內容為圖片
Android畫板開發(五) 添加文本文字

在上一篇實現了簡單的畫板功能, 這篇實現橡皮擦功能,首先分析一下應該如何實現:

在Andriod有個圖像混合(Xfermode)概念,利用這個概念我們就可以實現橡皮擦功能。

一、Xfermode

Paint有一個方法setXfermode(Xfermode),這個方法設置圖像的混合模式。參數有三個子類:

  • AvoidXfermode
  • PixelXorXfermode
  • PorterDuffXfermode

前面兩個因為不支持硬件加速在API 16已經已經過時棄用了。 簡單講一下第三個。

1.1 PorterDuffXfermode

該類有且只有一個含參的構造方法PorterDuffXfermode(PorterDuff.Mode mode),參數就是設置圖像的混合模式,下面這張圖片形象地說明了各種模式的作用

我們的做橡皮擦的時候,就是用到了PorterDuff.Mode.CLEAR這個模式清除圖像,所以說橡皮擦也是Path,只是繪制的模式不一樣了。

二、實現

在上一篇的文章中,實現了最簡單筆畫畫板,就是只有一個畫筆模式,所以首先添加一個橡皮擦的繪制模式。

companion object {const val EDIT_MODE_PEN = 0x1L //畫筆模式const val EDIT_MODE_ERASER = 0x2L //橡皮擦模式}@Retention(AnnotationRetention.SOURCE)@IntDef(EDIT_MODE_PEN, EDIT_MODE_ERASER)annotation class EditMode//當前編輯模式默認為畫筆模式@EditModeprivate var mMode: Long = EDIT_MODE_PEN/*** 設置畫筆模式*/fun setModel(@EditMode model:Long){mMode = modelwhen(model){EDIT_MODE_PEN -> {//畫線mPaint.xfermode = null}EDIT_MODE_ERASER ->{mPaint.xfermode = PorterDuffXfermode(PorterDuff.Mode.CLEAR)}}}

然后捋一下整個流程:

  • 畫筆模式,在onTouch時候畫出Path,繪制到view上
  • 然后切換到橡皮擦模式,畫出Path,clear擦掉原來的內容
  • 再來回切換繪制

現在重點是解決第2點,一個Path怎么做到不改變原來的path基礎上換個繪制模式繼續畫呢?

如果你考慮第2點的話,效果是這樣子的:

What the fuck?(黑人問號) 這什么情況? 其實是因為path只有一條,一直沒改變。所以,引入緩存Canvas和緩存Bitmap,添加兩個變量:

//想要繪制的內容先繪制到這個增加的canvas對應的bitmap上,// 寫完后再把這個bitmap的ARGB信息一次提交給上下文的canvas去繪制private lateinit var mBufferBitmap: Bitmapprivate lateinit var mBufferCanvas: Canvas

然后在onMeasure中進行初始化:

override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {super.onMeasure(widthMeasureSpec, heightMeasureSpec)if(mBufferCanvas == null){mBufferBitmap = Bitmap.createBitmap(measuredWidth, measuredHeight, Bitmap.Config.ARGB_8888)//canvas繪制的內容,將會在這個mBufferBitmap內mBufferCanvas = Canvas(mBufferBitmap)}}

然后在onTouchEvent方面里面手指移動的時候,我們在緩存Canvas里面進行繪制path:

MotionEvent.ACTION_MOVE -> { //手指移動的時候//繪制圓滑曲線,即貝塞爾曲線,貝塞爾曲線這個知識自行了解mPath.quadTo(preX,preY,event.x,event.y)//在緩存里面繪制mBufferCanvas.drawPath(mPath,mPaint)//重新繪制,會調用onDraw方法invalidate()preX = event.xpreY = event.y}

然后onDraw的時候,就把緩存的Canvas的bitmap當前view的Canvas:

override fun onDraw(canvas: Canvas) {super.onDraw(canvas)//畫出緩存bitmap的內容canvas.drawBitmap(mBufferBitmap,0f,0f,null)}

就可以了,看看完整的代碼100多行:

class TPEraserView(context: Context, attr: AttributeSet) : View(context,attr) {companion object {const val EDIT_MODE_PEN = 0x1L //畫筆模式const val EDIT_MODE_ERASER = 0x2L //橡皮擦模式}@Retention(AnnotationRetention.SOURCE)@IntDef(EDIT_MODE_PEN, EDIT_MODE_ERASER)annotation class EditMode//當前編輯模式默認為畫筆模式@EditModeprivate var mMode: Long = EDIT_MODE_PENprivate var preX: Float = 0.0f //上一次的觸摸點x坐標private var preY: Float = 0.0f //上一次觸摸點y坐標private var mPath = Path() //path路徑//畫筆private var mPaint = Paint(Paint.ANTI_ALIAS_FLAG or Paint.DITHER_FLAG)//想要繪制的內容先繪制到這個增加的canvas對應的bitmap上,// 寫完后再把這個bitmap的ARGB信息一次提交給上下文的canvas去繪制private lateinit var mBufferBitmap: Bitmapprivate lateinit var mBufferCanvas: Canvasinit {mPaint.style = Paint.Style.STROKE //畫筆為實心mPaint.color = Color.RED //顏色mPaint.strokeCap = Paint.Cap.ROUND //筆觸為圓形mPaint.strokeWidth = 10f //畫筆大小}override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int){super.onMeasure(widthMeasureSpec, heightMeasureSpec)mBufferBitmap = Bitmap.createBitmap(measuredWidth, measuredHeight, Bitmap.Config.ARGB_8888)//canvas繪制的內容,將會在這個mBufferBitmap內mBufferCanvas = Canvas(mBufferBitmap)}override fun onDraw(canvas: Canvas) {super.onDraw(canvas)//畫出緩存bitmap的內容canvas.drawBitmap(mBufferBitmap,0f,0f,null)}override fun onTouchEvent(event: MotionEvent): Boolean {when(event.action){MotionEvent.ACTION_DOWN -> { //手指按下的時候//將起始點移動到當前坐標mPath.moveTo(event.x,event.y)//記錄上次觸摸的坐標,注意ACTION_DOWN方法只會執行一次preX = event.xpreY = event.y}MotionEvent.ACTION_MOVE -> { //手指移動的時候//繪制圓滑曲線,即貝塞爾曲線,貝塞爾曲線這個知識自行了解mPath.quadTo(preX,preY,event.x,event.y)//在緩存里面繪制mBufferCanvas.drawPath(mPath,mPaint)//重新繪制,會調用onDraw方法invalidate()preX = event.xpreY = event.y}MotionEvent.ACTION_UP ->{//清除路徑的內容mPath.reset()}}// true:告訴系統,這個觸摸事件由我來處理// false:告訴系統,這個觸摸事件我不處理,這時系統會把觸摸事件傳遞給imageview的父節點return true}/*** 設置畫筆模式*/fun setModel(@EditMode model:Long){mMode = modelwhen(model){EDIT_MODE_PEN -> {mPaint.xfermode = null}EDIT_MODE_ERASER ->{mPaint.xfermode = PorterDuffXfermode(PorterDuff.Mode.CLEAR)}}}}

效果:

三、清空畫布實現

添加一個方法,按照上面的套路,把緩存canvas繪制清除即可。

/*** 清空畫布*/fun clear() {mBufferCanvas.drawColor(0, PorterDuff.Mode.CLEAR)invalidate()}

總結

以上是生活随笔為你收集整理的Android画板开发(二) 橡皮擦实现的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。