• 
    

      <address id="upfr9"><pre id="upfr9"><strike id="upfr9"></strike></pre></address>
      1. <address id="upfr9"><tr id="upfr9"></tr></address><dl id="upfr9"></dl>

        Android畫板開發(fā)之橡皮擦功能

        在上一篇實(shí)現(xiàn)了簡單的畫板功能, 這篇實(shí)現(xiàn)橡皮擦功能,首先分析一下應(yīng)該如何實(shí)現(xiàn),

        公司主營業(yè)務(wù):做網(wǎng)站、成都網(wǎng)站設(shè)計(jì)、移動(dòng)網(wǎng)站開發(fā)等業(yè)務(wù)。幫助企業(yè)客戶真正實(shí)現(xiàn)互聯(lián)網(wǎng)宣傳,提高企業(yè)的競爭能力。創(chuàng)新互聯(lián)建站是一支青春激揚(yáng)、勤奮敬業(yè)、活力青春激揚(yáng)、勤奮敬業(yè)、活力澎湃、和諧高效的團(tuán)隊(duì)。公司秉承以“開放、自由、嚴(yán)謹(jǐn)、自律”為核心的企業(yè)文化,感謝他們對我們的高要求,感謝他們從不同領(lǐng)域給我們帶來的挑戰(zhàn),讓我們激情的團(tuán)隊(duì)有機(jī)會(huì)用頭腦與智慧不斷的給客戶帶來驚喜。創(chuàng)新互聯(lián)建站推出高郵免費(fèi)做網(wǎng)站回饋大家。

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

        Android畫板開發(fā)之橡皮擦功能

        一、Xfermode

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

        • AvoidXfermode
        • PixelXorXfermode
        • PorterDuffXfermode

        前面兩個(gè)因?yàn)椴恢С钟布铀僭贏PI 16已經(jīng)已經(jīng)過時(shí)棄用了。 簡單講一下第三個(gè)。

        1.1 PorterDuffXfermode

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

        Android畫板開發(fā)之橡皮擦功能

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

        二、實(shí)現(xiàn)

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

        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
        
         //當(dāng)前編輯模式默認(rèn)為畫筆模式
         @EditMode
         private var mMode: Long = EDIT_MODE_PEN
        
         /**
          * 設(shè)置畫筆模式
          */
         fun setModel(@EditMode model:Long){
          mMode = model
          when(model){
           EDIT_MODE_PEN -> {
            //畫線
            mPaint.xfermode = null
           }
           EDIT_MODE_ERASER ->{
            mPaint.xfermode = PorterDuffXfermode(PorterDuff.Mode.CLEAR)
        
           }
          }
         }

        然后捋一下整個(gè)流程:

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

        現(xiàn)在重點(diǎn)是解決第2點(diǎn),一個(gè)Path怎么做到不改變原來的path基礎(chǔ)上換個(gè)繪制模式繼續(xù)畫呢?

        如果你考慮第2點(diǎn)的話,效果是這樣子的:

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

        //想要繪制的內(nèi)容先繪制到這個(gè)增加的canvas對應(yīng)的bitmap上,
        // 寫完后再把這個(gè)bitmap的ARGB信息一次提交給上下文的canvas去繪制
         private lateinit var mBufferBitmap: Bitmap
         private lateinit var mBufferCanvas: Canvas

        然后在onMeasure中進(jìn)行初始化:

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

        然后在onTouchEvent方面里面手指移動(dòng)的時(shí)候,我們在緩存Canvas里面進(jìn)行繪制path:

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

        然后onDraw的時(shí)候,就把緩存的Canvas的bitmap當(dāng)前view的Canvas:

        override fun onDraw(canvas: Canvas) {
          super.onDraw(canvas)
          //畫出緩存bitmap的內(nèi)容
          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
        
         //當(dāng)前編輯模式默認(rèn)為畫筆模式
         @EditMode
         private var mMode: Long = EDIT_MODE_PEN
        
         private var preX: Float = 0.0f //上一次的觸摸點(diǎn)x坐標(biāo)
         private var preY: Float = 0.0f //上一次觸摸點(diǎn)y坐標(biāo)
        
         private var mPath = Path() //path路徑
         //畫筆
         private var mPaint = Paint(Paint.ANTI_ALIAS_FLAG or Paint.DITHER_FLAG)
        
         //想要繪制的內(nèi)容先繪制到這個(gè)增加的canvas對應(yīng)的bitmap上,
         // 寫完后再把這個(gè)bitmap的ARGB信息一次提交給上下文的canvas去繪制
         private lateinit var mBufferBitmap: Bitmap
         private lateinit var mBufferCanvas: Canvas
        
        
         init {
          mPaint.style = Paint.Style.STROKE //畫筆為實(shí)心
          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繪制的內(nèi)容,將會(huì)在這個(gè)mBufferBitmap內(nèi)
          mBufferCanvas = Canvas(mBufferBitmap)
        
         }
        
         override fun onDraw(canvas: Canvas) {
          super.onDraw(canvas)
          //畫出緩存bitmap的內(nèi)容
          canvas.drawBitmap(mBufferBitmap,0f,0f,null)
        
         }
        
         override fun onTouchEvent(event: MotionEvent): Boolean {
        
          when(event.action){
           MotionEvent.ACTION_DOWN -> { //手指按下的時(shí)候
            //將起始點(diǎn)移動(dòng)到當(dāng)前坐標(biāo)
            mPath.moveTo(event.x,event.y)
        
            //記錄上次觸摸的坐標(biāo),注意ACTION_DOWN方法只會(huì)執(zhí)行一次
            preX = event.x
            preY = event.y
           }
           MotionEvent.ACTION_MOVE -> { //手指移動(dòng)的時(shí)候
            //繪制圓滑曲線,即貝塞爾曲線,貝塞爾曲線這個(gè)知識自行了解
            mPath.quadTo(preX,preY,event.x,event.y)
        
            //在緩存里面繪制
            mBufferCanvas.drawPath(mPath,mPaint)
        
            //重新繪制,會(huì)調(diào)用onDraw方法
            invalidate()
            preX = event.x
            preY = event.y
           }
           MotionEvent.ACTION_UP ->{
            //清除路徑的內(nèi)容
            mPath.reset()
           }
          }
        
          // true:告訴系統(tǒng),這個(gè)觸摸事件由我來處理
          // false:告訴系統(tǒng),這個(gè)觸摸事件我不處理,這時(shí)系統(tǒng)會(huì)把觸摸事件傳遞給imageview的父節(jié)點(diǎn)
          return true
         }
        
         /**
          * 設(shè)置畫筆模式
          */
         fun setModel(@EditMode model:Long){
          mMode = model
          when(model){
           EDIT_MODE_PEN -> {
            mPaint.xfermode = null
           }
           EDIT_MODE_ERASER ->{
            mPaint.xfermode = PorterDuffXfermode(PorterDuff.Mode.CLEAR)
        
           }
          }
         }
        
        }

        三、清空畫布實(shí)現(xiàn)

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

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

        以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持創(chuàng)新互聯(lián)。

        文章標(biāo)題:Android畫板開發(fā)之橡皮擦功能
        本文網(wǎng)址:http://www.jbt999.com/article34/jjesse.html

        成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供手機(jī)網(wǎng)站建設(shè)網(wǎng)站維護(hù)、自適應(yīng)網(wǎng)站、外貿(mào)網(wǎng)站建設(shè)小程序開發(fā)、電子商務(wù)

        廣告

        聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:[email protected]。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

        網(wǎng)站托管運(yùn)營

      2. 
        

          <address id="upfr9"><pre id="upfr9"><strike id="upfr9"></strike></pre></address>
          1. <address id="upfr9"><tr id="upfr9"></tr></address><dl id="upfr9"></dl>
            国产家庭乱轮 | 久久久蜜桃一区二区人 | 国产精品黄色电影 | 操逼网站在线视频 | 伊人大香蕉在线视频 | 亚洲高清视频免费在线观看 | 肏屄视频免费 | 精品国产AV网站 | 国产乱论视频 | 亚洲高潮视频 |