FlowLayout

2021-04-15  本文已影响0人  Ello_Orld

import android.content.Context
import android.util.AttributeSet
import android.util.Log
import android.view.View
import android.view.ViewGroup
import kotlin.math.max

/**
 * @author 
 * @date 4/8/008 9:55
 */
class FlowLayout @JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : ViewGroup(context, attrs, defStyleAttr) {
    
    //所有行
    private val lines = mutableListOf<Line>()

    //当前行
    private var line: Line? = null


    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)

        "onMeasure".log()

        //实际可用大小
        val width = MeasureSpec.getSize(widthMeasureSpec) - paddingLeft - paddingRight
        val height = MeasureSpec.getSize(heightMeasureSpec) - paddingTop - paddingBottom

        val widthMode = MeasureSpec.getMode(widthMeasureSpec)
        val heightMode = MeasureSpec.getMode(heightMeasureSpec)

        lines.clear()
        line = null

        for (i in 0 until childCount) {
            val child = getChildAt(i)
            //测量所有child
            measureChild(child, widthMeasureSpec, heightMeasureSpec)
            if (line == null) {
                newLine()
            }

            //当前view需要的宽度
            val measuredWidth = child.measuredWidth
            if (line!!.children.isEmpty()) {
                line!!.addChild(child)
            } else {
                if (line!!.width + measuredWidth > width) {
                    //放不下了
                    newLine()
                }
                line!!.addChild(child)
            }
        }

        var totalHeight = paddingTop + paddingBottom
        lines.forEach { totalHeight += it.height }

        "totalHeight = $totalHeight".log()

        setMeasuredDimension(
            MeasureSpec.getSize(widthMeasureSpec),
            resolveSize(totalHeight, heightMeasureSpec)
        )
    }



    private fun newLine() {
        "newLine".log()
        line = Line()
        lines.add(line!!)
    }

    override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
        var top = paddingTop
        lines.forEach {
            "lines.count = ${lines.size}".log()
            it.layout(paddingLeft, top )
            top += it.height
        }
    }


    inner class Line {
        val children = mutableListOf<View>()


        var height = 0
        var width = 0

        fun addChild(child: View) {
            children.add(child)
            height = max(height, child.measuredHeight)
            width += child.measuredWidth
        }

        fun layout(left: Int, top: Int) {
            var currentLeft = left
            for (child in children) {
                "childrenCount = ${children.size}, l = $currentLeft, t = $top, r = ${currentLeft + child.measuredWidth}, b = ${top + child.measuredHeight}".log()
                child.layout(
                    currentLeft,
                    top,
                    currentLeft + child.measuredWidth,
                    top + child.measuredHeight
                )

                currentLeft += child.measuredWidth
            }
        }
    }


}


fun Any?.log() {
    Log.d("dxl", this?.toString() ?: "----null")
}
上一篇下一篇

猜你喜欢

热点阅读