Hacktoberfest 2026: los issues que los mantenedores marcaron para octubre, abiertos y aptos para principiantes. Explorar issues de Hacktoberfest

Crash on ReadMoreText with IntrinsicSize

Abierto
#126 0 comentarios 0 reacciones 0 asignados Ver en GitHub

@fornewid ya está trabajando en esto.

Desde el 8/10/2026.

  • #127 de @fornewid — abierto

Evaluación

Dificultad
4/5
Tiempo estimado
3-5 días
Aptitud para principiantes
54/100
Tipo de issue
Error
Claridad
Bien especificado
Estado de actividad
Activo
Stack tecnológico
android, kotlin
Área
frontend, mobile

Línea de trabajo

Start in the CoreReadMoreText implementation and trace how BoxWithConstraints supplies the width used to calculate collapsed text. The proposal identifies replacing it with Box, recording width from BasicText's onTextLayout, and recalculating collapsed text; check the foundation, material, and material3 tests, including intrinsic-height measurement and width changes. Done means intrinsic measurement no longer crashes and the collapsed text updates correctly without public API changes.

Escrito por el modelo de indexación a partir del texto del issue.

Descripción

bug

Problem

ReadMoreText crashes when its parent asks for intrinsic measurements, for example Row(Modifier.height(IntrinsicSize.Max)). This applies to BasicReadMoreText and to the material and material3 wrappers.

java.lang.IllegalStateException: Asking for intrinsic measurements of SubcomposeLayout layouts is not supported. This includes components that are built on top of SubcomposeLayout, such as lazy lists, BoxWithConstraints, TabRow, etc. To mitigate this:

Since 1.7.0 (#93), CoreReadMoreText wraps BasicText in BoxWithConstraints to read constraints.maxWidth for TextMeasurer. BoxWithConstraints is built on SubcomposeLayout, which does not support intrinsic measurements.

A common case is a horizontal carousel whose cards all match the tallest one:

Row(
    modifier = Modifier
        .horizontalScroll(rememberScrollState())
        .height(IntrinsicSize.Max),
) {
    posts.forEach { post ->
        Column(Modifier.width(292.dp).fillMaxHeight()) {
            ReadMoreText(
                text = post.body,
                expanded = false,
                readMoreText = "more",
                readMoreMaxLines = 3,
            )
        }
    }
}

Proposal

BoxWithConstraints is only used for constraints.maxWidth. BasicText already reports the same value through onTextLayout (TextLayoutResult.layoutInput.constraints), and onTextLayout is called only for the real layout, not for intrinsic measurements.

  1. Replace BoxWithConstraints with Box.
  2. Keep maxWidth in a state and update it from onTextLayout.
  3. Compute the collapsed text with remember(maxWidth, ...) instead of LaunchedEffect. ReadMoreState.applyCollapsedText() becomes calculateCollapsedText(), which returns the collapsed text. Its body stays the same.

The collapsed text is still measured from the original text with TextMeasurer. Only the width source changes. No public API changes.

     val textMeasurer = rememberTextMeasurer()
-    val state = remember { ReadMoreState() }
+    var maxWidth by remember { mutableIntStateOf(UnknownWidth) }
+    val collapsedText = remember(
+        textMeasurer,
+        maxWidth,
+        overflowText,
+        readMoreTextWithStyle,
+        style,
+        readMoreStyle,
+        text,
+        readMoreMaxLines,
+        softWrap,
+        inlineContent,
+    ) {
+        if (maxWidth == UnknownWidth) {
+            AnnotatedString("")
+        } else {
+            calculateCollapsedText(
+                textMeasurer = textMeasurer,
+                constraints = Constraints(maxWidth = maxWidth),
+                overflowText = overflowText,
+                readMoreTextWithStyle = readMoreTextWithStyle,
+                style = style,
+                readMoreStyle = readMoreStyle,
+                text = text,
+                readMoreMaxLines = readMoreMaxLines,
+                softWrap = softWrap,
+                inlineContent = inlineContent,
+            )
+        }
+    }
+    val isCollapsible = collapsedText.isNotEmpty()
 ...
-    BoxWithConstraints(
+    Box(
         modifier = modifier
             .then(toggleableModifier)
             .padding(contentPadding),
     ) {
         BasicText(
             text = currentText,
             modifier = Modifier,
             style = style,
-            onTextLayout = onTextLayout,
+            onTextLayout = { result ->
+                maxWidth = result.layoutInput.constraints.maxWidth
+                onTextLayout(result)
+            },
             overflow = TextOverflow.Ellipsis,
             softWrap = softWrap,
             maxLines = if (expanded) Int.MAX_VALUE else readMoreMaxLines,
             inlineContent = inlineContent,
         )
-
-        val constraints = Constraints(maxWidth = constraints.maxWidth)
-        LaunchedEffect(
-            ...
-        ) {
-            state.applyCollapsedText(...)
-        }
     }

Checked with a local prototype

  • verifyRoborazziDebug passes for readmore-foundation, readmore-material and readmore-material3 (168 cases) with no image changes.
  • In Row(Modifier.height(IntrinsicSize.Max)) it no longer crashes, and the last line ends with … more.
  • When the width changes from 300dp to 200dp and then to 320dp, the collapsed text is recalculated each time.
  • Frame timing is the same as now. The first frame shows the original text with an ellipsis, and the next frame shows the collapsed text with "more".

Alternatives considered

  • Capturing the constraints in Modifier.layout {}: its measure block also runs for intrinsic queries, so the state would be written during intrinsic passes. onTextLayout runs only for the real layout.
  • A custom Layout that measures with TextMeasurer and draws with drawText(): the collapsed text would be ready in the first frame, but it would lose what BasicText provides, such as LinkAnnotation for ToggleArea.More, semantics and inlineContent.
Lenguaje dominante
Kotlin
Estrellas
209
Forks
14
Métricas de merge de PR
Sin PR fusionados en 30 d

Preparar el entorno

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Más de webtoon/ReadMoreTextView

Todos los issues de webtoon/ReadMoreTextView

Issues similares

Más issues de Kotlin

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.