一个很low的viewgroup改写

改写一个随着子控件的摆放,当到达viewgroup的宽度时自动换行的view

思路:在onMeasure里计算控件的宽高并计算好摆放的位置,然后根据父控件的宽度来考虑是否要换行

直接上代码:

package com.example.opencvapplication

import android.content.Context
import android.graphics.Rect
import android.graphics.RectF
import android.util.AttributeSet
import android.util.Log
import android.view.View
import android.view.ViewGroup
import androidx.core.view.children
import androidx.core.view.marginBottom
import androidx.core.view.marginTop
import kotlin.math.max

class SteamViewGrop(context: Context?, attrs: AttributeSet?) : ViewGroup(context, attrs) {

    val rectList = ArrayList<Rect>()

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
//        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
        var startLeft = 0
        var startTop = 0
        var maxHeight = 0
        var usedHeight = 0
        val viewWidth = MeasureSpec.getSize(widthMeasureSpec)
        val viewHeight = MeasureSpec.getSize(widthMeasureSpec)
        Log.e("xxj", "viewWidth=$viewWidth")
        for ((index, child) in children.withIndex()) {
            //计算子控件的宽高
            measureChildWithMargins(child,widthMeasureSpec,0,heightMeasureSpec,viewHeight-usedHeight)
            val margin = child.layoutParams as MarginLayoutParams
            maxHeight =max(maxHeight, child.measuredHeight + margin.bottomMargin + margin.topMargin)//取当前行最大的高度

            if (startLeft + child.measuredWidth > viewWidth) {//当宽度大于父控件的宽度时换行
                startTop += maxHeight
                usedHeight += maxHeight
                maxHeight = 0
                startLeft = 0
                //重新计算宽高
                measureChildWithMargins(child,widthMeasureSpec,0,heightMeasureSpec,viewHeight-usedHeight)

            }
            Log.e("xxj", "startLeft=$startLeft  startTop=$startTop  child.width=${child.measuredWidth}")
            if (index >= rectList.size) {
                rectList.add(Rect())
            }
            rectList[index].set(//设置子控件的位置
                startLeft + margin.leftMargin,
                startTop + margin.topMargin,
                startLeft + margin.leftMargin + child.measuredWidth,
                startTop + margin.topMargin + child.measuredHeight
            )

            startLeft += child.measuredWidth + margin.rightMargin
        }
        usedHeight += maxHeight
        setMeasuredDimension(viewWidth, usedHeight)
    }

    override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
        for ((index, child) in children.withIndex()) {
            child.layout(
                rectList[index].left,
                rectList[index].top,
                rectList[index].right,
                rectList[index].bottom
            )
        }
    }

    override fun generateLayoutParams(attrs: AttributeSet?): LayoutParams {
        return MarginLayoutParams(context, attrs)
    }

}

使用:

<?xml version="1.0" encoding="utf-8"?>
<com.example.opencvapplication.SteamViewGrop xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".activity.MainActivity">

    <TextView
        style="@style/textStyle"
        android:text="伊利丹" />

    <TextView
        style="@style/textStyle"

        android:text="维伦" />

    <TextView
        style="@style/textStyle"
        android:text="基尔加丹" />

    <TextView
        style="@style/textStyle"

        android:text="格鲁姆.地狱咆哮" />

    <TextView
        style="@style/textStyle"

        android:text="玛法里奥.怒风" />

    <TextView
        style="@style/textStyle"

        android:text="帕克" />

    <TextView
        style="@style/textStyle"

        android:text="戴泽" />

    <TextView
        style="@style/textStyle"

        android:text="卡尔" />

    <TextView
        style="@style/textStyle"

        android:text="凯尔萨斯" />

    <TextView
        style="@style/textStyle"

        android:text="瓦里安.乌瑞恩" />


</com.example.opencvapplication.SteamViewGrop>

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值