實戰酷斃了的自定義View(三)

Gtihub傳送門

前言

在以前咱們講到過了PaintCanvas的一些用法,可是其實還不能解決所有問題,在咱們的項目中你是否是有須要這樣的東西——滑動和動畫。對!!如何實現像RecyclerView的滑動效果,和一個動畫效果,接下來咱們將會講到。git

滑動

其實爲了尋求方便,直接使用的是Android已經封裝好的類GestureDetector。內部存在一個簡單的手勢分辨的內部類SimpleOnGestureListener,咱們能夠直接調用而後完成滑動這個動做。github

private inner class BarGesture : SimpleOnGestureListener() {

        override fun onDown(e: MotionEvent?): Boolean {
            return true
        }

        override fun onScroll( e1: MotionEvent?, e2: MotionEvent?, distanceX: Float, distanceY: Float ): Boolean {
            if (mBarShowNum <= mMinBarScrollShowNum) return false

            val position = dp2px(context, scrollX.toFloat())
            if (distanceX >= 0) {
                if (position <= mBarMaxWidth) {
                    scrollBy(distanceX.toInt(), 0)
                }
            } else {
                if (distanceX >= -1 * position) {
                    scrollBy(distanceX.toInt(), 0)
                }
            }
            return false
        }
    }
複製代碼

爲了滑動,自動會有一個距離的要求了,咱們調用View已經定義好的ScrollBy,就能夠進行挪移了。canvas

整體來講,其實他已經給咱們封裝好了,要作的就是一個方向的判斷。另外在代碼中咱們能看到scrollX這個變量,這是View已經定義好的一個變量,記住他等等有大用。ide

關於性能

在以前咱們講到過一個問題,就是Android的座標系是怎樣的。有所遺忘的讀者們能夠重溫一下Android自定義View,你摸的透透的了?對於超出屏幕寬度的圖案咱們是否會進行繪製呢?post

咱們對整個繪製作一個測驗好了,下面先給出測試代碼性能

override fun onDraw(canvas: Canvas?) {
        super.onDraw(canvas)
        // 1
        var count:Int = 0
        for (i in mData!!.indices) {
// if (!checkIsNeedDraw(i)) {
                val height = (mMaxData - mData!![i]) / mMaxData * mBarMaxHeight
                mBarPaint?.shader = null
                drawBarValue(canvas, i, height)
                drawDescriptions(canvas, i)
                mBarPaint?.shader = shader
                drawBars(canvas, height)
                // 2
                count++
// }
            if (i != mData!!.size - 1) {
                canvas?.translate(mBarSingleWidth, 0f)
            }
        }
        // 3
        Log.e("onDraw", count.toString())
    }
複製代碼

標註的代碼在BarChartView類的源碼中加一下就行了。我給出的數據量是7個,那看看結果給出是幾回呢!!!學習

Oh my God!!!7次,真的是7次,個人天吶,那不就是說,我超出的部分你也要畫????我要你有啥用啊,你別給我畫呀。測試

算了算了,知道了要繪製,那咱們就要找解決方案了。咱們剛剛說起到了一個scrollX這個變量,其實就是記錄咱們當前屏幕最左邊相對於座標軸而言的,在座標X軸的哪一個位置了,而屏幕大小又是固定的,那咱們就能夠引伸出這樣的想法。動畫

引伸出的代碼以下

private fun checkIsNeedDraw(i: Int): Boolean {
        if (mBarSingleWidth * (i + 1) < scrollX) return true
        if (mBarSingleWidth * i > scrollX + mWidth) return true
        return false
    }
複製代碼

看看加了他的效果把。ui

出現了6着數值,說明咱們繪製的數量明顯減小了不是。證實方法有效!!!!

動畫

動畫實際上是一個很大的知識點了,這裏不會仔細講這個,一方面是由於他的知識容量大,一方面是個人接觸的還不夠全面。

private fun initAnimation() {
        animator = ValueAnimator.ofFloat(0.3f, 1f)
        // 經過插值器來完成動畫
        animator?.interpolator = LinearInterpolator()
        animator?.duration = 1500
        animator?.addUpdateListener { animation ->
            scale = animation.animatedValue as Float
            postInvalidate()
        }
    }
複製代碼

先來看看個人代碼好了。咱們能看到一個LinearInterpolator()這樣的玩意兒,定位一下他,就能夠看到他的你們族成員有誰了。

經過動畫時間的設定,和一個scale也就是值的改變,動態的更改數據,其實也就是不斷重繪,來完成咱們所可以看到的逐漸增加的效果。想一想也應該沒有這麼困難了,你能夠直接調用這些類,來完成一些簡單的動畫效果。

柱狀圖的繪製

重頭戲,重頭戲!!!

其實咱們以前已經考慮了不少我在寫柱狀圖的時候遇到的一些問題了,因此大體上的話仍是以看源碼爲基準,這裏主要展現的仍是個人一個設計稿,由於你要去繪製一個柱狀圖的話,確定是要有必定的計算的。

基本就是靠這個簡陋的設計稿完成的個人這個類的了,有Bug請見諒。

不過也一樣但願你能Star一下個人這個項目View_How_To_Make_It

以上就是個人學習成果,若是有什麼我沒有思考到的地方或是文章內存在錯誤,歡迎與我分享。


相關文章推薦:

實戰酷斃了的自定義View(二)

實戰酷斃了的自定義View(一)

【從零衝擊音視頻開發】FFmpeg的介紹和基本使用

相關文章
相關標籤/搜索