Home > Mobile >  Jetpack Compose Layout is there a way to determine measurable type or id when building custom compon
Jetpack Compose Layout is there a way to determine measurable type or id when building custom compon

Time:10-04

Is there a way to determine which measurable is what kind of component is Row, Column, Box, or a custom component?

@Composable
fun MyCustomComponent(
    modifier: Modifier = Modifier,
    content: @Composable () -> Unit
) {
    Layout(
        modifier = modifier,
        content = content
    ) { measurables, constraints ->
        // measure and position children given constraints logic here

    }
}

Consider this as a chat layout with name on top but only in group chats when it's a row that sent by other participants, quoted text available only when a user quotes, image or message and some other type. And doing some operations based on availability of any of these components. And order is not fixed, you might not know the order of any component under every condition, it might change based on different situations. With Views this is possible by checking ids or checking View's instance type

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

    // some other stuff

    val parent = parent as LinearLayout

    val quotedMessageLayout = parent.findViewById<ViewGroup>(R.id.quoted_message_frame)

    val userNameLayout = parent.findViewById<ViewGroup>(R.id.layoutUserName)

    if (quotedMessageLayout != null && quotedMessageLayout.visibility == VISIBLE) {

        if (widthFlexBox < quotedMessageLayout.measuredWidth) {

            val quoteParams = quotedMessageLayout.layoutParams as LinearLayout.LayoutParams
            val quoteWidth = quotedMessageLayout.measuredWidth   quoteParams.marginStart   quoteParams.marginEnd
            val quoteMaxSize = min(parentWidth, quoteWidth)
            widthFlexBox = max(widthFlexBox, quoteMaxSize)
        }
    }

    if (userNameLayout != null && userNameLayout.visibility == VISIBLE) {
        if (widthFlexBox < userNameLayout.measuredWidth) {

            val userNameParams = userNameLayout.layoutParams as LinearLayout.LayoutParams
            val userNameWidth = userNameLayout.measuredWidth   userNameParams.marginStart   userNameParams.marginEnd
            val userNameMaxSize = min(parentWidth, userNameWidth)
            widthFlexBox = max(widthFlexBox, userNameMaxSize)
        }
    }

    setMeasuredDimension(widthFlexBox, heightFlexBox)
}

Checking out this article about creating custom modifiers, it makes me think can i add type modifiers to Composable functions or even better way to check out which Composable it is from measureables?

CodePudding user response:

You can add layoutId to views inside your content using Modifier.layoutId, and then read these values from measurables.

enum class LayoutId {
    Box,
    Row,
}

@Composable
fun TestScreen(
) {
    Layout(content = {
        Box(Modifier.layoutId(LayoutId.Box)) {

        }
        Row(Modifier.layoutId(LayoutId.Row)) {

        }
    }) { measurables, constraints ->
        measurables.forEach { measurable ->
            when (val layoutId = measurable.layoutId as? LayoutId) {
                LayoutId.Box -> {
                    println("box found")
                }
                LayoutId.Row -> {
                    println("row found")
                }
                null -> {
                    println("unknown layout id: ${measurable.layoutId}")
                }
            }
        }
        layout(0, 0) {

        }
    }
}
  • Related