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) {
}
}
}