Android 화판 개발 에 텍스트 추가

머리말
텍스트 를 추가 하 는 것 도 비교적 간단 한 기능 입 니 다.두 번 째 편 에 서 는 지우 개 를 추가 하고 지우개 에 하나의 패턴 으로 붓 을 그 리 는 판단 을 합 니 다.물론 텍스트 도 마찬가지 입 니 다.텍스트 모드 를 추가 하고 onTouch Down 에 서 는 PopupWindow 를 연주 하고 텍스트 를 입력 한 다음 에 PopupWindow 가 사라 질 때.static Layout 를 이용 하여 캔버스 에 그리 면 됩 니 다.물론 주의해 야 할 부분도 있 습 니 다.

다음 단계 로 넘 어가 도록 하 겠 습 니 다.
실현
2.1 텍스트 모드 추가
예 를 들 어 지우개 처럼 텍스트 모드 를 하나 더 추가 한 다음 setModel 을 사용 할 때 펜 스타일 을 FILL 로 수정 해 야 합 니 다.STROKE 가 텍스트 를 그리 면 빈 텍스트 가 됩 니 다.

companion object {
    const val EDIT_MODE_PEN = 0x1L    //    
    const val EDIT_MODE_ERASER = 0x2L  //     
    const val EDIT_MODE_TEXT = 0x3L  //    

  }

  @Retention(AnnotationRetention.SOURCE)
  @IntDef(EDIT_MODE_PEN, EDIT_MODE_ERASER, EDIT_MODE_TEXT)
  annotation class EditMode

  /**
   *       
   */
  fun setModel(@EditMode model: Long) {
    mMode = model
    when (model) {
      EDIT_MODE_PEN -> {
        //  
        mPaint.xfermode = null
        mPaint.style = Paint.Style.STROKE
      }
      EDIT_MODE_ERASER -> {
        mPaint.xfermode = PorterDuffXfermode(PorterDuff.Mode.CLEAR)

      }
      EDIT_MODE_TEXT -> {
        mPaint.style = Paint.Style.FILL
      }
    }
  }
2.2 bean 형식 수정
Static Layout 는 편집 할 수 없 는 텍스트 레이아웃 을 위 한 클래스 입 니 다.이것 은 레이아웃 이 완성 되면 텍스트 내용 을 바 꿀 수 없다 는 것 을 의미 합 니 다.단순히 TextView 를 사용 하여 정적 텍스트 를 보 여줄 때 만 든 것 은 Static Layout 입 니 다.api 25,Textview 원본 6858 줄 에서 볼 수 있 습 니 다.

StaticLayout.Builder builder = StaticLayout.Builder.obtain(mHint, 0,
     mHint.length(), mTextPaint, hintWidth)
     .setAlignment(alignment)
     .setTextDirection(mTextDir)
     .setLineSpacing(mSpacingAdd, mSpacingMult)
     .setIncludePad(mIncludePad)
     .setBreakStrategy(mBreakStrategy)
     .setHyphenationFrequency(mHyphenationFrequency);
우리 화판 의 그리 기 문자 도 이 Static Layout 를 사 용 했 습 니 다.세 가지 구조 방법 이 있 습 니 다.우 리 는 최소한 그것 을 사용 하면 됩 니 다.

public StaticLayout(CharSequence source, //   
   TextPaint paint, //    
   int width,  //layout   ,            。
   Layout.Alignment align, //layout     , ALIGN_CENTER, ALIGN_NORMAL, ALIGN_OPPOSITE   。
   float spacingmult,  //     ,      ,1.5f      1.5      。
   float spacingadd,  //          
   boolean includepad)  //           
그래서 bean 류 는 이전 을 바탕 으로 텍스트,너비,xy 축의 오프셋 을 추가 한 다음 에 그 릴 때 static Layout 를 이용 하여 그 렸 습 니 다.

data class PaintBean(
    var mPaint: Paint,  //    
    var mPath: Path?,     //    
    var mText: String,    //  
    var mWidth: Int,
    var mOffX: Float,
    var mOffY: Float,
    private @TPTextView.EditMode var mMode:Long
) {

  constructor(mPaint: Paint, mPath: Path) : this(mPaint,mPath,"",0,0f,0f,TPTextView.EDIT_MODE_PEN)

  /**
   *              
   * @param canvas      
   */
  fun draw(canvas: Canvas){

    when(mMode){

      TPTextView.EDIT_MODE_TEXT -> {

        if(!TextUtils.isEmpty(mText)){
          //            
          canvas.translate(mOffX,mOffY)
          //  staticLayout    ,      
          val staticLayout = StaticLayout(mText,mPaint as TextPaint,mWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false)
          staticLayout.draw(canvas)
          //Log.e("@@","  :"+staticLayout.width)
          //canvas.drawText(mText,mTextOffX,mTextOffY,mPaint)
          //      
          canvas.translate(-mOffX,-mOffY)

        }

      }
      else -> {
        canvas.drawPath(mPath,mPaint)
      }

    }

  }

  fun getMode():Long = mMode

}
2.3 탄창 처리
다음은 팝 업 윈도 우 를 설정 하여 텍스트 입력 을 합 니 다.팝 업 창 에 있 는 컨트롤 은 EditText 입 니 다.팝 업 창 이 사라 질 때 붓 목록 에 추가 하고 다시 그립 니 다.여기 서 세 가지 주의 점 이 있어 요.
  • 소프트 키보드 자동 팝 업
  • 편집 상자 가 소프트 키보드 위 에 표 시 됩 니 다
  • 탄 상자 에 표 시 된 위치
  • 오른쪽 크로스
  • 
    private var mTextPopup: PopupWindow? = null
    private var mTextView: EditText? = null
    
      /**
       *   popup      
       */
      private fun showTextPopup() {
    
        if (null == mTextPopup) {
          mTextView = EditText(context)
          mTextView?.hint = "  "
    
          mTextPopup = PopupWindow(mTextView,
              WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT,
              true)
          mTextPopup?.setOnDismissListener {
            if (!TextUtils.isEmpty(mTextView?.text)) {
              //     
              mPaintedList.add(
                  PaintBean(TextPaint(mPaint), null, mTextView?.text.toString(), (width - preX).toInt(),preX,preY - mTextView!!.height / 2, EDIT_MODE_TEXT))
    
              invalidate()
            }
          }
          // popup        
          mTextPopup?.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE
        }
    
        mTextView?.requestFocus()
    
        //       ,       ,   、  
        val imm = context.getSystemService(Service.INPUT_METHOD_SERVICE) as InputMethodManager
        imm.toggleSoftInput(0, InputMethodManager.HIDE_NOT_ALWAYS)
    
    
        mTextPopup?.showAtLocation(this, Gravity.TOP and Gravity.LEFT, preX.toInt(), preY.toInt()+mTextView!!.height)
    
      }
    만 질 때 표시 합 니 다.이동 할 때 는 조작 하지 않 고 손가락 이 일 어 났 을 때 도 조작 하지 않 는 다.
    
    @SuppressLint("ClickableViewAccessibility")
      override fun onTouchEvent(event: MotionEvent): Boolean {
    
        when (event.action) {
          MotionEvent.ACTION_DOWN -> { //       
            //         ,  ACTION_DOWN        
            preX = event.x
            preY = event.y
            when (mMode) {
    
              EDIT_MODE_TEXT -> {
                //  popupWidnwo  text
                showTextPopup()
                //           list
              }
              else -> {
                //           
                mPath.moveTo(event.x, event.y)
                mPaintedList.add(PaintBean(Paint(mPaint), Path(mPath)))
              }
            }
    
          }
          MotionEvent.ACTION_MOVE -> { //       
            when (mMode) {
              EDIT_MODE_TEXT -> {
    
              }
              else -> {
                //      ,      ,             
                mPaintedList.get(mPaintedList.size - 1).mPath?.quadTo(preX, preY, event.x, event.y)
                preX = event.x
                preY = event.y
                //    ,   onDraw  
                invalidate()
              }
    
            }
          }
          MotionEvent.ACTION_UP -> {}
        }
    
        return true
      }
    bean 클래스 에 그 려 져 있 기 때문에 view 의 onDraw 방법 은 예전 처럼 변 할 필요 가 없습니다.
    
    @SuppressLint("DrawAllocation")
      override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)
    
        //           bitmap
        while (mPaintedList.size > PAINT_RECORED_NUM) {
          val paint = mPaintedList.removeAt(0)
          paint.draw(mHoldCanvas!!)
        }
    
        //          Canvas
        mBufferCanvas?.drawBitmap(mHoldBitmap, 0f, 0f, null)
    
        //       
        for (paint in mPaintedList) {
          paint.draw(mBufferCanvas!!)
        }
    
        //    bitmap   
        canvas.drawBitmap(mBufferBitmap, 0f, 0f, null)
    
      }
    이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

    좋은 웹페이지 즐겨찾기