最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Android畫(huà)板開(kāi)發(fā)之撤銷反撤銷功能

 更新時(shí)間:2018年12月20日 10:39:37   作者:tpnet  
這篇文章主要為大家詳細(xì)介紹了Android畫(huà)板開(kāi)發(fā)之撤銷,反撤銷功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

一、分析

這篇將會(huì)講解撤銷反撤銷功能的實(shí)現(xiàn),先討論一下這個(gè)原理是怎么樣實(shí)現(xiàn)的。

每次撤回的內(nèi)容,內(nèi)容是怎么定義呢? 其實(shí)就是每一筆,每一筆作為撤回的內(nèi)容,那每一筆怎么算呢,就是算手指從按下-移動(dòng)-放開(kāi)這一個(gè)過(guò)程就是一筆。

我們只需記錄這個(gè)過(guò)程為一筆,然后用一個(gè)已畫(huà)列表list列表來(lái)記錄這個(gè)過(guò)程的paint畫(huà)筆和路徑path。

撤銷的時(shí)候就把后面的一個(gè)數(shù)據(jù)移到另一個(gè)撤銷列表

反撤銷的時(shí)候,就把撤銷列表的最后面那條數(shù)據(jù)移動(dòng)到已畫(huà)列表。

然后,還有一個(gè)重點(diǎn),就是畫(huà)筆的保存數(shù)量,上面說(shuō)記錄每一筆畫(huà)筆,這當(dāng)然是有個(gè)限度,不可能畫(huà)了好幾百筆都記錄下來(lái),這樣子內(nèi)存消耗很大的,所以超出顯示畫(huà)筆數(shù)量的時(shí)候,我們就把以前的畫(huà)死在畫(huà)板上。

基本原理是這樣子的。接下來(lái)跟著我實(shí)現(xiàn)

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

如何實(shí)現(xiàn)撤回功能

2.1 定義數(shù)據(jù)類

首先,需要一個(gè)bean類存儲(chǔ)每一筆的數(shù)據(jù),這里定義一個(gè)PaintData,里面需要定義個(gè)draw方法,因?yàn)槌蜂N的時(shí)候,需要重新繪制。

data class PaintData(
    var mPaint: Paint,  //保存畫(huà)筆

    var mPath: Path     //保存路徑
) {
  /**
   * 撤銷和反撤銷之后 重新繪制
   * @param canvas 繪制的畫(huà)布
   */
  fun draw(canvas: Canvas){
    canvas.drawPath(mPath,mPaint)
  }

}

2.2 修改清空畫(huà)板方法

因?yàn)槎嗔肆斜?,所以清空?huà)板的方法需要把列表也清除了

/**
   * 清空畫(huà)布
   * @param isClearList 時(shí)候清空數(shù)據(jù)列表
*/
  fun clear(isClearList:Boolean) {
    if(isClearList){
      mRevokedList.clear()
      mPaintedList.clear()
    }
    mBufferCanvas.drawColor(0, PorterDuff.Mode.CLEAR)
    invalidate()
  }

2.3 實(shí)現(xiàn)撤銷方法

在view定義兩個(gè)列表,一個(gè)是已經(jīng)畫(huà)的內(nèi)容列表,一個(gè)是撤銷內(nèi)容的列表

//儲(chǔ)存已經(jīng)寫(xiě)的筆畫(huà)
private var mPaintedList: MutableList<PaintData> = ArrayList<PaintData>()

//已經(jīng)撤銷的列表
private var mRevokedList: MutableList<PaintData> = ArrayList<PaintData>()

添加固話層canvas和bitmap,超出記錄的畫(huà)筆就寫(xiě)死在固化層了

//固化層,超出最大筆畫(huà)就先繪制到這個(gè)層
private lateinit var mHoldBitmap: Bitmap
private lateinit var mHoldCanvas: Canvas

//最多記錄20畫(huà)筆跡
private val MAX_PAINT_RECORED = 20 


  //在測(cè)量的時(shí)候進(jìn)行初始化:
  override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
    if(mBufferCanvas == null){
      mBufferBitmap = Bitmap.createBitmap(measuredWidth, measuredHeight, Bitmap.Config.ARGB_8888)

      //canvas繪制的內(nèi)容,將會(huì)在這個(gè)mBufferBitmap內(nèi)
      mBufferCanvas = Canvas(mBufferBitmap)
    }


    if(mHoldCanvas == null){
      mHoldBitmap = Bitmap.createBitmap(measuredWidth, measuredHeight, Bitmap.Config.ARGB_8888)
      mHoldCanvas = Canvas(mHoldBitmap)
    }
  }

然后定義撤回的方法

/**
 * 撤回一個(gè)筆跡
 * @return 是否撤回成功
*/
  fun revoked(){
    reDraw(mPaintedList)
  }

反撤銷方法基本一致,只是改了個(gè)列表:

 /**
   * 反撤回一個(gè)筆跡
   */
  fun unRevoked(){
    reDraw(mRevokedList)
}

然后重新繪制的方法為:

/**
   * 重新繪制
   * @param paintList 需要操作的list
 */
  private fun reDraw(paintList:MutableList<PaintData>){

    if(paintList.size > 0){
      val paint = paintList.removeAt(paintList.size-1)
      if(paintList === mPaintedList){
        mRevokedList.add(paint)
      }else{
        mPaintedList.add(paint)
      }

      //清空緩存畫(huà)板
      mBufferCanvas.drawColor(0, PorterDuff.Mode.CLEAR)

      invalidate()

    }
  }

然后就是畫(huà)筆的保存,在觸摸按下的時(shí)候,進(jìn)行畫(huà)筆的保存

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

        //保存畫(huà)筆
        mPaintedList.add(PaintData(Paint(mPaint),Path(mPath)))

      }
      MotionEvent.ACTION_MOVE -> { //手指移動(dòng)的時(shí)候

        //繪制圓滑曲線,即貝塞爾曲線,貝塞爾曲線這個(gè)知識(shí)自行了解
        mPaintedList.get(mPaintedList.size-1).mPath.quadTo(preX,preY,event.x,event.y)

        //重新繪制,會(huì)調(diào)用onDraw方法
        invalidate()

        preX = event.x
        preY = event.y
      }
      MotionEvent.ACTION_UP ->{

        //清除路徑的內(nèi)容
        mPath.reset()

      }
    }

    // true:告訴系統(tǒng),這個(gè)觸摸事件由我來(lái)處理
    // false:告訴系統(tǒng),這個(gè)觸摸事件我不處理,這時(shí)系統(tǒng)會(huì)把觸摸事件傳遞給imageview的父節(jié)點(diǎn)
    return true
  }

最后繪制的時(shí)候:

override fun onDraw(canvas: Canvas) {
    super.onDraw(canvas)


    //超出緩存的就固化到緩存bitmap
    while(mPaintedList.size > MAX_PAINT_RECORED){
      val paintData = mPaintedList.removeAt(0)
      paintData.draw(mHoldCanvas)
    }

    //繪制固化的內(nèi)容到緩存Canvas
    mBufferCanvas.drawBitmap(mHoldBitmap,0f,0f,null)

    //繪制記錄的畫(huà)筆
    for(paint in mPaintedList){
      //重新繪制每個(gè)path
      paint.draw(mBufferCanvas)
    }


    //畫(huà)出緩存bitmap的內(nèi)容
    canvas.drawBitmap(mBufferBitmap,0f,0f,null)

  }

最后清除畫(huà)布的時(shí)候,需要把畫(huà)筆列表也清除了:

/**
   * 清空畫(huà)布
*/
  fun clear() {
    mRevokedList.clear()
    mPaintedList.clear()
    mHoldCanvas.drawColor(0, PorterDuff.Mode.CLEAR)
    mBufferCanvas.drawColor(0, PorterDuff.Mode.CLEAR)
    invalidate()

  }

重點(diǎn)就是在于利用一個(gè)bean類來(lái)保存每筆的 畫(huà)筆和路徑,然后撤銷時(shí)候重新繪制。

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

最新評(píng)論

资溪县| 隆安县| 宾川县| 清河县| 大英县| 科尔| 隆尧县| 通辽市| 凤阳县| 永川市| 浑源县| 泽库县| 田林县| 惠安县| 古交市| 道孚县| 揭东县| 木里| 永寿县| 崇仁县| 麻江县| 东平县| 页游| 合江县| 辰溪县| 屏东市| 都昌县| 宁陕县| 宁安市| 衡山县| 冷水江市| 炎陵县| 富蕴县| 宁晋县| 库尔勒市| 沈阳市| 河曲县| 绥棱县| 两当县| 四川省| 波密县|