안 드 로 이 드 화판 개발 의 지우개 기능

지난 편 에 서 는 간단 한 패 널 기능 을 실현 하 였 으 며,이 편 은 지우개 기능 을 실현 하 였 으 며,먼저 어떻게 실현 해 야 하 는 지 분석 하 였 다.
Andriod 에 이미지 혼합(Xfermode)개념 이 있 는데 이 개념 을 이용 하면 우 리 는 지우개 기능 을 실현 할 수 있다.

1.Xfermode
Paint 는 그림 의 혼합 모드 를 설정 하 는 방법 이 있 습 니 다.매개 변 수 는 세 개의 하위 클래스 가 있 습 니 다.
  • AvoidXfermode
  • PixelXorXfermode
  • PorterDuffXfermode
  • 앞의 두 개 는 하드웨어 가속 을 지원 하지 않 기 때문에 API 16 에서 이미 시간 이 지 났 습 니 다.간단하게 세 번 째.
    1.1 PorterDuffXfermode
    이 종 류 는 인삼 을 포함 하 는 구조 방법 만 있 습 니 다.Porter Duff Xfermode(Porter Duff.Mode mode)는 매개 변 수 는 이미지 의 혼합 모델 을 설정 하 는 것 입 니 다.아래 그림 은 각종 모델 의 역할 을 이미지 적 으로 설명 합 니 다.

    우리 가 지우 개 를 만 들 때 Porter Duff.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 에 그립 니 다
  • 4.567917.그리고 지우개 모드 로 전환 하여 Path 를 그리고 clear 는 원래 의 내용 을 지 웁 니 다.
  • 다시 왔다갔다 그리 기
  • 지금 중요 한 것 은 두 번 째 점 을 해결 하 는 것 입 니 다.하나의 Path 는 어떻게 원래 의 path 를 바 꾸 지 않 고 그림 모드 를 바 꾸 어 계속 그 릴 수 있 습 니까?
    만약 당신 이 두 번 째 점 을 고려한다 면 효 과 는 다음 과 같 습 니 다.
    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)
    
       }
      }
     }
    
    }
    3.캔버스 비우 기 실현
    위의 방법 에 따라 캐 시 canvas 를 그립 니 다.
    
     /**
      *     
      */
     fun clear() {
      mBufferCanvas.drawColor(0, PorterDuff.Mode.CLEAR)
      invalidate()
     }
    이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

    좋은 웹페이지 즐겨찾기