summaryrefslogtreecommitdiff
path: root/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/EqualWidthContainer.kt
blob: 6f56874eb895b124f52d1f1dc6c22c747e6b8879 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
package com.android.permissioncontroller.safetycenter.ui

import android.content.Context
import android.util.AttributeSet
import android.view.View.MeasureSpec.EXACTLY
import android.widget.LinearLayout
import android.widget.Space
import androidx.core.view.children

/**
 * A [LinearLayout] that requires all its children (except [Space]s) to be the same width. The
 * layout is horizontal, unless the buttons don't fit in which case it moves to vertical.
 *
 * Assumes its children are all WRAP_CONTENT width and that it is some fixed width (either
 * MATCH_PARENT or sized by constraint - not WRAP_CONTENT itself).
 */
class EqualWidthContainer @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :
    LinearLayout(context, attrs) {

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        // super.onMeasure will cause all children to be measured in the default way
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)

        // Separate children into spaces and non-spaces
        val (spaces, nonSpaceItems) = children.partition { it is Space }
        val neededWidthPerNonSpaceItem =
            try {
                nonSpaceItems.maxOf { it.measuredWidth }
            } catch (e: NoSuchElementException) {
                0
            }
        val neededWidth = neededWidthPerNonSpaceItem * nonSpaceItems.count()

        // Switch between horizontal or vertical layout as needed
        val availableWidth =
            MeasureSpec.getSize(widthMeasureSpec) - spaces.sumOf { it.measuredWidth }
        orientation = if (neededWidth <= availableWidth) HORIZONTAL else VERTICAL

        // Measure again now orientation has changed
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)

        // Re-measure all the children with EXACT width (using previously calculated height)
        nonSpaceItems.forEach {
            it.measure(
                MeasureSpec.makeMeasureSpec(neededWidthPerNonSpaceItem, EXACTLY),
                MeasureSpec.makeMeasureSpec(it.measuredHeight, EXACTLY))
        }
    }
}