Skip to content

Commit f2fae1b

Browse files
committed
Fix that '... Read more' area would not be clickable if a hyperlink and '... Read more' text are overlapped
1 parent 32ec804 commit f2fae1b

File tree

5 files changed

+106
-40
lines changed

5 files changed

+106
-40
lines changed

readmore-foundation/src/main/java/com/webtoonscorp/android/readmore/foundation/BasicReadMoreText.kt

Lines changed: 97 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import androidx.compose.runtime.setValue
3333
import androidx.compose.ui.Modifier
3434
import androidx.compose.ui.text.AnnotatedString
3535
import androidx.compose.ui.text.LinkAnnotation
36+
import androidx.compose.ui.text.LinkInteractionListener
3637
import androidx.compose.ui.text.Placeholder
3738
import androidx.compose.ui.text.SpanStyle
3839
import androidx.compose.ui.text.TextLayoutResult
@@ -192,8 +193,9 @@ public fun BasicReadMoreText(
192193
// CoreReadMoreText
193194
// ////////////////////////////////////
194195

195-
private const val ReadMoreTag = "read_more"
196-
private const val ReadLessTag = "read_less"
196+
private const val ReadMoreTag = "readmore:read_more"
197+
private const val ReadLessTag = "readmore:read_less"
198+
private const val ContentsTag = "readmore:contents"
197199

198200
@SuppressLint("UnusedBoxWithConstraintsScope")
199201
@Composable
@@ -254,41 +256,28 @@ private fun CoreReadMoreText(
254256
val state = remember { ReadMoreState() }
255257

256258
val currentText = buildAnnotatedString {
257-
if (expanded) {
258-
append(text)
259-
if (state.isCollapsible && readLessTextWithStyle.isNotEmpty()) {
260-
append(' ')
261-
if (toggleArea == ToggleArea.More) {
262-
withLink(
263-
LinkAnnotation.Clickable(tag = ReadLessTag) {
264-
onExpandedChange?.invoke(false)
265-
},
266-
) {
267-
append(readLessTextWithStyle)
268-
}
269-
} else {
270-
append(readLessTextWithStyle)
271-
}
272-
}
273-
} else {
274-
val collapsedText = state.collapsedText
275-
if (collapsedText.isNotEmpty()) {
276-
append(collapsedText)
277-
append(overflowText)
278-
279-
if (toggleArea == ToggleArea.More) {
280-
withLink(
281-
LinkAnnotation.Clickable(tag = ReadMoreTag) {
282-
onExpandedChange?.invoke(true)
283-
},
284-
) {
285-
append(readMoreTextWithStyle)
286-
}
287-
} else {
288-
append(readMoreTextWithStyle)
289-
}
259+
withContentsLink(
260+
hasLink = onExpandedChange != null && toggleArea == ToggleArea.All
261+
&& text.hasLinks() && state.isCollapsible,
262+
linkInteractionListener = { onExpandedChange?.invoke(!expanded) },
263+
) {
264+
if (expanded) {
265+
appendExpandedText(
266+
text = text,
267+
onExpandedChange = onExpandedChange,
268+
readLessTextWithStyle = readLessTextWithStyle,
269+
toggleArea = toggleArea,
270+
isCollapsible = state.isCollapsible,
271+
)
290272
} else {
291-
append(text)
273+
appendCollapsedText(
274+
text = text,
275+
collapsedText = state.collapsedText,
276+
overflowText = overflowText,
277+
onExpandedChange = onExpandedChange,
278+
readMoreTextWithStyle = readMoreTextWithStyle,
279+
toggleArea = toggleArea,
280+
)
292281
}
293282
}
294283
}
@@ -345,6 +334,78 @@ private fun CoreReadMoreText(
345334
}
346335
}
347336

337+
private fun AnnotatedString.Builder.appendCollapsedText(
338+
text: AnnotatedString,
339+
collapsedText: AnnotatedString,
340+
overflowText: String,
341+
onExpandedChange: ((Boolean) -> Unit)?,
342+
readMoreTextWithStyle: AnnotatedString,
343+
toggleArea: ToggleArea,
344+
) {
345+
if (collapsedText.isNotEmpty()) {
346+
append(collapsedText)
347+
append(overflowText)
348+
349+
if (toggleArea == ToggleArea.More) {
350+
withLink(
351+
LinkAnnotation.Clickable(tag = ReadMoreTag) {
352+
onExpandedChange?.invoke(true)
353+
},
354+
) {
355+
append(readMoreTextWithStyle)
356+
}
357+
} else {
358+
append(readMoreTextWithStyle)
359+
}
360+
} else {
361+
append(text)
362+
}
363+
}
364+
365+
private fun AnnotatedString.Builder.appendExpandedText(
366+
text: AnnotatedString,
367+
onExpandedChange: ((Boolean) -> Unit)?,
368+
readLessTextWithStyle: AnnotatedString,
369+
toggleArea: ToggleArea,
370+
isCollapsible: Boolean,
371+
) {
372+
append(text)
373+
if (isCollapsible && readLessTextWithStyle.isNotEmpty()) {
374+
append(' ')
375+
if (toggleArea == ToggleArea.More) {
376+
withLink(
377+
LinkAnnotation.Clickable(tag = ReadLessTag) {
378+
onExpandedChange?.invoke(false)
379+
},
380+
) {
381+
append(readLessTextWithStyle)
382+
}
383+
} else {
384+
append(readLessTextWithStyle)
385+
}
386+
}
387+
}
388+
389+
private inline fun <R : Any> AnnotatedString.Builder.withContentsLink(
390+
hasLink: Boolean,
391+
linkInteractionListener: LinkInteractionListener?,
392+
block: AnnotatedString.Builder.() -> R,
393+
): R {
394+
return if (hasLink) {
395+
withLink(
396+
LinkAnnotation.Clickable(
397+
tag = ContentsTag,
398+
linkInteractionListener = linkInteractionListener,
399+
),
400+
block = block,
401+
)
402+
} else {
403+
block()
404+
}
405+
}
406+
407+
private fun AnnotatedString.hasLinks() = hasLinkAnnotations(0, length)
408+
348409
// ////////////////////////////////////
349410
// ReadMoreState
350411
// ////////////////////////////////////

sample/src/main/java/com/webtoonscorp/android/readmore/sample/compose/foundation/BasicReadMoreTextDemo.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -592,7 +592,9 @@ private fun Item_Hyperlink(showMessage: (String) -> Unit) {
592592
withLink(
593593
LinkAnnotation.Clickable(
594594
tag = "TAG$index",
595-
styles = TextLinkStyles(style = SpanStyle(color = Color.Blue)),
595+
styles = TextLinkStyles(
596+
style = SpanStyle(color = Color.Blue),
597+
),
596598
) {
597599
showMessage("#TAG$index Clicked!")
598600
},

sample/src/main/java/com/webtoonscorp/android/readmore/sample/compose/material/ReadMoreTextDemo.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -554,7 +554,9 @@ private fun Item_Hyperlink(showMessage: (String) -> Unit) {
554554
withLink(
555555
LinkAnnotation.Clickable(
556556
tag = "TAG$index",
557-
styles = TextLinkStyles(style = SpanStyle(color = Color.Blue)),
557+
styles = TextLinkStyles(
558+
style = SpanStyle(color = Color.Blue),
559+
),
558560
) {
559561
showMessage("#TAG$index Clicked!")
560562
},

sample/src/main/java/com/webtoonscorp/android/readmore/sample/compose/material3/ReadMoreTextDemo.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -573,7 +573,9 @@ private fun Item_Hyperlink(showMessage: (String) -> Unit) {
573573
withLink(
574574
LinkAnnotation.Clickable(
575575
tag = "TAG$index",
576-
styles = TextLinkStyles(style = SpanStyle(color = Color.Blue)),
576+
styles = TextLinkStyles(
577+
style = SpanStyle(color = Color.Blue),
578+
),
577579
) {
578580
showMessage("#TAG$index Clicked!")
579581
},

sample/src/main/res/layout/item_hyperlink.xml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626
android:layout_marginTop="5dp"
2727
android:layout_marginEnd="18dp"
2828
android:layout_marginBottom="18dp"
29-
android:background="?selectableItemBackground"
3029
android:lineSpacingExtra="4sp"
3130
android:textColor="?colorOnSurface"
3231
android:textSize="15sp"

0 commit comments

Comments
 (0)