美文网首页
自己写一个流式布局

自己写一个流式布局

作者: 壹元伍角叁分 | 来源:发表于2021-08-15 20:56 被阅读0次
class FlowViewGroup2(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) : ViewGroup(context, attrs, defStyleAttr) {
    private val LEFT_MARGIN = 20
    private val TOP_MARGIN = 10
    private var childViewList: MutableList<MutableList<View>> = ArrayList()
    private var oneLineHeightList: MutableList<Int> = ArrayList()

    constructor(context: Context) : this(context, null, 0)

    constructor(context: Context, attrs: AttributeSet) : this(context, attrs, 0)

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        clearViewList()

        val widthMeasureSize = MeasureSpec.getSize(widthMeasureSpec)//测量的父控件宽
        val heightMeasureSize = MeasureSpec.getSize(heightMeasureSpec)//测量的父控件高
        val paddingLeft = paddingLeft
        val paddingRight = paddingRight
        val paddingTop = paddingTop
        val paddingBottom = paddingBottom

        var usedParentWidth = 0//已使用的父控件宽
        var usedParentHeight = 0//已使用的父控件高

        var realParentWidth = 0
        var realParentHeight = 0

        var oneLineHeight = 0

        var oneLineChildViewList: MutableList<View> = ArrayList()
        val childCount1 = childCount
        for (childIndex in 0 until childCount1) {
            val childView = getChildAt(childIndex)
            if (childView.visibility != GONE) {
                val childLayoutParams = childView.layoutParams
                val childWidthMeasureSpec = getChildMeasureSpec(widthMeasureSpec, paddingLeft + paddingRight, childLayoutParams.width)
                val childHeightMeasureSpec = getChildMeasureSpec(heightMeasureSpec, paddingTop + paddingBottom, childLayoutParams.height)
                childView.measure(childWidthMeasureSpec, childHeightMeasureSpec)

                val measuredWidth = childView.measuredWidth
                val measuredHeight = childView.measuredHeight

                if (usedParentWidth + LEFT_MARGIN + measuredWidth > widthMeasureSize) {
                    //超过了一屏,切换行吧
                    childViewList.add(oneLineChildViewList)
                    oneLineHeightList.add(oneLineHeight)
                    realParentWidth = Math.max(usedParentWidth, widthMeasureSize)
                    realParentHeight += TOP_MARGIN + oneLineHeight

                    //重置,
                    oneLineChildViewList = ArrayList()
                    oneLineHeight = 0
                    usedParentWidth = 0
                }

                //
                usedParentWidth += LEFT_MARGIN + measuredWidth
                oneLineChildViewList.add(childView)
                oneLineHeight = Math.max(measuredHeight + TOP_MARGIN, oneLineHeight)

                //最后一行的高度需要加上
                if (childIndex == childCount1 - 1) {
                    childViewList.add(oneLineChildViewList)
                    oneLineHeightList.add(oneLineHeight)
                    realParentWidth = Math.max(usedParentWidth, widthMeasureSize)
                    realParentHeight += TOP_MARGIN + oneLineHeight
                }
            }
        }

        //子控件全部测量完成后,去进行布局吧。
        //但是先去获取下父控件的类型
        val widthMeasureMode = MeasureSpec.getMode(widthMeasureSpec)
        val heightMeasureMode = MeasureSpec.getMode(heightMeasureSpec)

        val layoutParentWidth = if (widthMeasureMode == MeasureSpec.EXACTLY) {
            widthMeasureSize
        } else {
            realParentWidth
        }

        val layoutParentHeight = if (heightMeasureMode == MeasureSpec.EXACTLY) {
            heightMeasureSize
        } else {
            realParentHeight
        }

        setMeasuredDimension(layoutParentWidth, layoutParentHeight)
    }

    private fun clearViewList() {
        childViewList.clear()
        oneLineHeightList.clear()
    }


    override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
        //去遍历
        var parentUseLeft = paddingLeft
        var parentUseHeight = paddingTop
        for (onlineChildViewListIndex in childViewList.indices) {
            val childViewList = childViewList[onlineChildViewListIndex]//获取一行的view
            val oneLineHeight = oneLineHeightList[onlineChildViewListIndex]//获取这行的高

            for (index in childViewList.indices) {
                val view = childViewList[index]

                val childLeft = parentUseLeft
                val childTop = parentUseHeight
                val childRight = parentUseLeft + view.measuredWidth
                val childBottom = parentUseHeight + view.measuredHeight
                view.layout(childLeft, childTop, childRight, childBottom)

                parentUseLeft = LEFT_MARGIN + childRight
            }
            parentUseLeft = paddingLeft
            parentUseHeight += oneLineHeight + TOP_MARGIN
        }
    }
}

相关文章

网友评论

      本文标题:自己写一个流式布局

      本文链接:https://www.haomeiwen.com/subject/taevbltx.html