亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 系統 > Android > 正文

Android畫板開發之橡皮擦功能

2019-10-21 21:32:38
字體:
來源:轉載
供稿:網友

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

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

Android,畫板,橡皮擦

一、Xfermode

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

  • AvoidXfermode
  • PixelXorXfermode
  • PorterDuffXfermode

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

1.1 PorterDuffXfermode

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

Android,畫板,橡皮擦

我們的做橡皮擦的時候,就是用到了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 //當前編輯模式默認為畫筆模式 @EditMode private var mMode: Long = EDIT_MODE_PEN /**  * 設置畫筆模式  */ fun setModel(@EditMode model:Long){  mMode = model  when(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: Bitmap private 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.x  preY = 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 //當前編輯模式默認為畫筆模式 @EditMode private var mMode: Long = EDIT_MODE_PEN private 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: Bitmap private lateinit var mBufferCanvas: Canvas init {  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.x    preY = event.y   }   MotionEvent.ACTION_MOVE -> { //手指移動的時候    //繪制圓滑曲線,即貝塞爾曲線,貝塞爾曲線這個知識自行了解    mPath.quadTo(preX,preY,event.x,event.y)    //在緩存里面繪制    mBufferCanvas.drawPath(mPath,mPaint)    //重新繪制,會調用onDraw方法    invalidate()    preX = event.x    preY = event.y   }   MotionEvent.ACTION_UP ->{    //清除路徑的內容    mPath.reset()   }  }  // true:告訴系統,這個觸摸事件由我來處理  // false:告訴系統,這個觸摸事件我不處理,這時系統會把觸摸事件傳遞給imageview的父節點  return true } /**  * 設置畫筆模式  */ fun setModel(@EditMode model:Long){  mMode = model  when(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開發頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
青青久久aⅴ北条麻妃| 午夜精品久久久久久久久久久久久| 国内精品久久久久久久久| 日韩成人在线电影网| 亚洲一区二区中文| 久久综合九色九九| 日本国产一区二区三区| 亚洲一区二区日本| 亚洲人成五月天| 91九色国产社区在线观看| 亚洲精品小视频在线观看| 久热精品在线视频| 97精品视频在线观看| 91精品国产高清自在线| 中文字幕自拍vr一区二区三区| 欧美午夜视频在线观看| 久久久99免费视频| 久久成人精品一区二区三区| 亚洲福利影片在线| 日韩精品999| 国内偷自视频区视频综合| 国产精品一区二区久久久久| 亚洲欧美日韩一区在线| 国产成人精品一区二区在线| 成人av色在线观看| 亚洲成人a级网| 欧美成人在线免费| 538国产精品一区二区免费视频| 欧美精品九九久久| 91av在线免费观看| 色777狠狠综合秋免鲁丝| 中文字幕自拍vr一区二区三区| 欧美一区视频在线| 国产精品久久久久久亚洲影视| 国产福利精品在线| 91在线免费视频| 亚洲a成v人在线观看| 国自在线精品视频| 国产精品日韩av| 亚洲黄色www| 92国产精品久久久久首页| 亚洲激情在线视频| 中文字幕欧美专区| 欧美成年人视频| 亚洲天堂视频在线观看| 欧美日韩美女视频| 国产美女精品视频免费观看| 欧美丝袜第一区| 国产一区二区黄| 亚洲理论电影网| 在线亚洲男人天堂| 亚洲国产精品高清久久久| 91香蕉电影院| 欧美怡红院视频一区二区三区| 91久久国产精品91久久性色| 亚洲第一黄色网| 成人免费大片黄在线播放| 成人免费淫片aa视频免费| 人人爽久久涩噜噜噜网站| 中文字幕亚洲天堂| 欧美激情按摩在线| 亚洲精品一区av在线播放| 亚洲国产又黄又爽女人高潮的| 亚洲精品wwwww| 亚洲欧美国产精品va在线观看| 国产精品中文字幕在线| 亚洲欧美综合区自拍另类| 91精品视频在线播放| 日本精品视频在线观看| 久久精品亚洲精品| 久久久久久久999| 日韩欧美aⅴ综合网站发布| 亚洲高清福利视频| 操91在线视频| 91亚洲精品在线观看| 亚洲国产女人aaa毛片在线| 欧美另类高清videos| 日韩亚洲一区二区| 久久久久久久影视| 91po在线观看91精品国产性色| 欧美电影免费观看高清完整| 69影院欧美专区视频| 91热精品视频| 亚洲老板91色精品久久| 久久久国产91| 国产91在线播放九色快色| 精品久久久999| 欧美激情精品久久久久久黑人| 国产一区二区视频在线观看| 国产v综合v亚洲欧美久久| 久久亚洲国产精品| 日韩网站免费观看| 日韩美女视频免费看| 91久久久久久久久久久| 97在线看免费观看视频在线观看| 97欧美精品一区二区三区| 亚洲三级黄色在线观看| 欧美在线视频一区二区| 欧美高清理论片| 欧美在线精品免播放器视频| 超碰91人人草人人干| 久久伊人免费视频| 两个人的视频www国产精品| 国产精品九九九| 中文字幕精品一区久久久久| 国产成人久久久精品一区| 国产精品高潮呻吟久久av无限| 亚洲国产一区自拍| 欧美第一淫aaasss性| 国产欧美在线看| 国产精品亚洲视频在线观看| 亚洲国产日韩欧美综合久久| 精品美女永久免费视频| 深夜福利国产精品| 色综合视频网站| 成人网在线视频| 欧美性黄网官网| 亚洲一区二区免费| 亚洲欧美日韩天堂一区二区| 久久久精品2019中文字幕神马| 成人黄色网免费| 欧美在线一区二区三区四| 亚洲一区二区三区视频播放| 成人免费视频在线观看超级碰| 欧美成人久久久| 庆余年2免费日韩剧观看大牛| 精品视频在线观看日韩| 亚洲精品久久久久久久久久久| 亚洲性猛交xxxxwww| 欧美人在线视频| 亚洲男子天堂网| 国产精品av免费在线观看| 欧美成人中文字幕| 亚洲国产精品国自产拍av秋霞| 日韩精品在线观看视频| 久久久久久中文| 日韩少妇与小伙激情| 日韩电影中文字幕在线| 中文字幕日韩精品在线观看| 国产精品入口尤物| 欧美精品在线观看91| 国产欧美一区二区白浆黑人| 国产欧美va欧美va香蕉在| 久久这里有精品视频| 国产在线观看精品一区二区三区| 久久久精品在线观看| 伊人一区二区三区久久精品| 久久精品电影一区二区| 精品少妇一区二区30p| 日本精品久久久| 美女av一区二区三区| 国产亚洲精品久久久久久| 国产999精品久久久影片官网| 久久精品久久久久| 日韩在线观看免费全| 亚洲www视频| 欧美视频在线观看免费| 97香蕉久久超级碰碰高清版| 欧美精品一区二区免费| 日韩精品在线播放| 亚洲一区二区久久| 一本色道久久88综合日韩精品| 国产成人自拍视频在线观看| 4438全国亚洲精品在线观看视频|