短視訊平臺原始碼,自定義流式佈局--kotlin

zhibo系統開發發表於2021-12-06

短視訊平臺原始碼,自定義流式佈局--kotlin實現的相關程式碼

一、使用原因

1.流式佈局中放了許多小的view,要求我們把這些子view妥善的擺放在一個viewgroup中,如果我們在xmL中去實現這個效果,這就要求我們去對每個子view設定margin,padding,還有位置屬性。這可能需要花很多時間去擺放,去設定。

2.如果我們做一個搜尋內容的歷史記錄,那麼我們事先是不知道子view的條目和具體內容的,所以我們也沒法在XML中去書寫,那麼我們就需要一個viewgroup去對資料進行操作,取自動生成子view,並把他們的位置擺放妥當。

二、使用步驟

1.建立一個類繼承viewgroup

程式碼如下:


class TagLayout(context: Context?, attrs: AttributeSet?) : ViewGroup(context, attrs)

2.重寫onMeasure方法

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        //擺放時所有子view佔據的橫向邊界
        var widthUsed = 0
        //所有子view佔據的縱向高度
        var heightUsed = 0
        //當前行的子view佔據的寬度
        var lineWidthUsed = 0
        //當前行佔據的縱向高度
        var lineMaxHeight = 0
        //拿到佈局的期望寬度
        val widthMeasureSpecSize = MeasureSpec.getSize(widthMeasureSpec)
        for ((index, child) in children.withIndex()) {
            //給child進行測量
            measureChildWithMargins(
                child,
                widthMeasureSpec,
                0,
                heightMeasureSpec,
                heightUsed
            )
            //超出邊界時換行
            if (child.measuredWidth + lineWidthUsed > widthMeasureSpecSize) {
                //累加這行的高度
                heightUsed += lineMaxHeight
                //新開一行,還沒有子view,下面兩個值置為零
                lineWidthUsed = 0
                lineMaxHeight = 0
                //由於新開了一行,則對子view進行重新測量
                measureChildWithMargins(
                    child,
                    widthMeasureSpec,
                    lineWidthUsed,
                    heightMeasureSpec,
                    heightUsed
                )
            }
            //如果存放子view對應位置的childrenBounds中還沒有存放過這個子view的Rect,則進行新增,避免在onMeasure中對物件進行重複建立。
            if (index >= childrenBounds.size) {
                childrenBounds.add(
                    Rect()
                )
            }
            //設定child 的位置和大小
            childrenBounds[index].set(
                lineWidthUsed,
                heightUsed,
                lineWidthUsed + child.measuredWidth,
                heightUsed + child.measuredHeight
            )
            //把新加的子view的寬度進行累加
            lineWidthUsed += child.measuredWidth
            //更新已加入的所有子view佔據的寬度
            widthUsed = max(widthUsed, lineWidthUsed)
            //更新當前行的view中最高的view高度,既這行子view所佔據的高度
            lineMaxHeight = max(lineMaxHeight, child.measuredHeight)
        }
        //獲取到所有子view佔據的高度,因為最後一行的view高度沒有在迴圈中進行累加,所有迴圈結束要記得加上
        val selfHeight = heightUsed + lineMaxHeight
        //獲取所有子view佔據的寬度
        val selfWidth = widthUsed
        setMeasuredDimension(selfWidth, selfHeight)
    }


小結

1.在onMeasure中測量每個子view的大小和位置,並用一個Rect的List用來記錄,以供後面onlayout中使用,並且在測量完所有子view後得到viewgroup最合適的大小

2.該處使用0作為第三個引數widthUsed,這是為什麼呢?

 measureChildWithMargins(
                child,
                widthMeasureSpec,
                0,
                heightMeasureSpec,
                heightUsed
            )


以上就是 短視訊平臺原始碼,自定義流式佈局--kotlin實現的相關程式碼,更多內容歡迎關注之後的文章


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69978258/viewspace-2845960/,如需轉載,請註明出處,否則將追究法律責任。

相關文章