国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統 > Android > 正文

Android畫板開發之撤銷反撤銷功能

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

一、分析

這篇將會講解撤銷反撤銷功能的實現,先討論一下這個原理是怎么樣實現的。

每次撤回的內容,內容是怎么定義呢? 其實就是每一筆,每一筆作為撤回的內容,那每一筆怎么算呢,就是算手指從按下-移動-放開這一個過程就是一筆。

我們只需記錄這個過程為一筆,然后用一個已畫列表list列表來記錄這個過程的paint畫筆和路徑path。

撤銷的時候就把后面的一個數據移到另一個撤銷列表

反撤銷的時候,就把撤銷列表的最后面那條數據移動到已畫列表。

然后,還有一個重點,就是畫筆的保存數量,上面說記錄每一筆畫筆,這當然是有個限度,不可能畫了好幾百筆都記錄下來,這樣子內存消耗很大的,所以超出顯示畫筆數量的時候,我們就把以前的畫死在畫板上。

Android,畫板,撤銷,反撤銷

基本原理是這樣子的。接下來跟著我實現

二、實現

如何實現撤回功能

2.1 定義數據類

首先,需要一個bean類存儲每一筆的數據,這里定義一個PaintData,里面需要定義個draw方法,因為撤銷的時候,需要重新繪制。

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

2.2 修改清空畫板方法

因為多了列表,所以清空畫板的方法需要把列表也清除了

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

2.3 實現撤銷方法

在view定義兩個列表,一個是已經畫的內容列表,一個是撤銷內容的列表

//儲存已經寫的筆畫private var mPaintedList: MutableList<PaintData> = ArrayList<PaintData>()//已經撤銷的列表private var mRevokedList: MutableList<PaintData> = ArrayList<PaintData>()

添加固話層canvas和bitmap,超出記錄的畫筆就寫死在固化層了

//固化層,超出最大筆畫就先繪制到這個層private lateinit var mHoldBitmap: Bitmapprivate lateinit var mHoldCanvas: Canvas//最多記錄20畫筆跡private val MAX_PAINT_RECORED = 20   //在測量的時候進行初始化:  override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {    if(mBufferCanvas == null){      mBufferBitmap = Bitmap.createBitmap(measuredWidth, measuredHeight, Bitmap.Config.ARGB_8888)      //canvas繪制的內容,將會在這個mBufferBitmap內      mBufferCanvas = Canvas(mBufferBitmap)    }    if(mHoldCanvas == null){      mHoldBitmap = Bitmap.createBitmap(measuredWidth, measuredHeight, Bitmap.Config.ARGB_8888)      mHoldCanvas = Canvas(mHoldBitmap)    }  }

然后定義撤回的方法

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

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

 /**   * 反撤回一個筆跡   */  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)      }      //清空緩存畫板      mBufferCanvas.drawColor(0, PorterDuff.Mode.CLEAR)      invalidate()    }  }

然后就是畫筆的保存,在觸摸按下的時候,進行畫筆的保存

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        //保存畫筆        mPaintedList.add(PaintData(Paint(mPaint),Path(mPath)))      }      MotionEvent.ACTION_MOVE -> { //手指移動的時候        //繪制圓滑曲線,即貝塞爾曲線,貝塞爾曲線這個知識自行了解        mPaintedList.get(mPaintedList.size-1).mPath.quadTo(preX,preY,event.x,event.y)        //重新繪制,會調用onDraw方法        invalidate()        preX = event.x        preY = event.y      }      MotionEvent.ACTION_UP ->{        //清除路徑的內容        mPath.reset()      }    }    // true:告訴系統,這個觸摸事件由我來處理    // false:告訴系統,這個觸摸事件我不處理,這時系統會把觸摸事件傳遞給imageview的父節點    return true  }

最后繪制的時候:

override fun onDraw(canvas: Canvas) {    super.onDraw(canvas)    //超出緩存的就固化到緩存bitmap    while(mPaintedList.size > MAX_PAINT_RECORED){      val paintData = mPaintedList.removeAt(0)      paintData.draw(mHoldCanvas)    }    //繪制固化的內容到緩存Canvas    mBufferCanvas.drawBitmap(mHoldBitmap,0f,0f,null)    //繪制記錄的畫筆    for(paint in mPaintedList){      //重新繪制每個path      paint.draw(mBufferCanvas)    }    //畫出緩存bitmap的內容    canvas.drawBitmap(mBufferBitmap,0f,0f,null)  }

最后清除畫布的時候,需要把畫筆列表也清除了:

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

重點就是在于利用一個bean類來保存每筆的 畫筆和路徑,然后撤銷時候重新繪制。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。


注:相關教程知識閱讀請移步到Android開發頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 庆安县| 沙湾县| 子洲县| 泾源县| 建宁县| 白城市| 灵宝市| 朔州市| 龙里县| 永城市| 金坛市| 通州区| 延安市| 汉源县| 建瓯市| 原平市| 团风县| 西乌珠穆沁旗| 兰州市| 永州市| 江阴市| 濮阳县| 淮滨县| 卫辉市| 醴陵市| 察雅县| 阳西县| 手机| 岚皋县| 巨野县| 怀安县| 林芝县| 北辰区| 博爱县| 文登市| 龙南县| 山阴县| 云南省| 唐河县| 淳化县| 寿宁县|