Skip to content

Commit 8cbf8df

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

5 files changed

Lines changed: 104 additions & 40 deletions

File tree

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

Lines changed: 95 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import androidx.compose.runtime.setValue
3131
import androidx.compose.ui.Modifier
3232
import androidx.compose.ui.text.AnnotatedString
3333
import androidx.compose.ui.text.LinkAnnotation
34+
import androidx.compose.ui.text.LinkInteractionListener
3435
import androidx.compose.ui.text.SpanStyle
3536
import androidx.compose.ui.text.TextLayoutResult
3637
import androidx.compose.ui.text.TextMeasurer
@@ -185,8 +186,9 @@ public fun BasicReadMoreText(
185186
// CoreReadMoreText
186187
// ////////////////////////////////////
187188

188-
private const val ReadMoreTag = "read_more"
189-
private const val ReadLessTag = "read_less"
189+
private const val ReadMoreTag = "readmore:read_more"
190+
private const val ReadLessTag = "readmore:read_less"
191+
private const val ContentsTag = "readmore:contents"
190192

191193
@Composable
192194
private fun CoreReadMoreText(
@@ -245,41 +247,27 @@ private fun CoreReadMoreText(
245247
val state = remember { ReadMoreState() }
246248

247249
val currentText = buildAnnotatedString {
248-
if (expanded) {
249-
append(text)
250-
if (readLessTextWithStyle.isNotEmpty()) {
251-
append(' ')
252-
if (toggleArea == ToggleArea.More) {
253-
withLink(
254-
LinkAnnotation.Clickable(tag = ReadLessTag) {
255-
onExpandedChange?.invoke(false)
256-
},
257-
) {
258-
append(readLessTextWithStyle)
259-
}
260-
} else {
261-
append(readLessTextWithStyle)
262-
}
263-
}
264-
} else {
265-
val collapsedText = state.collapsedText
266-
if (collapsedText.isNotEmpty()) {
267-
append(collapsedText)
268-
append(overflowText)
269-
270-
if (toggleArea == ToggleArea.More) {
271-
withLink(
272-
LinkAnnotation.Clickable(tag = ReadMoreTag) {
273-
onExpandedChange?.invoke(true)
274-
},
275-
) {
276-
append(readMoreTextWithStyle)
277-
}
278-
} else {
279-
append(readMoreTextWithStyle)
280-
}
250+
withContentsLink(
251+
hasLink = onExpandedChange != null && toggleArea == ToggleArea.All
252+
&& text.hasLinks() && state.isCollapsible,
253+
linkInteractionListener = { onExpandedChange?.invoke(!expanded) },
254+
) {
255+
if (expanded) {
256+
appendExpandedText(
257+
text = text,
258+
onExpandedChange = onExpandedChange,
259+
readLessTextWithStyle = readLessTextWithStyle,
260+
toggleArea = toggleArea,
261+
)
281262
} else {
282-
append(text)
263+
appendCollapsedText(
264+
text = text,
265+
collapsedText = state.collapsedText,
266+
overflowText = overflowText,
267+
onExpandedChange = onExpandedChange,
268+
readMoreTextWithStyle = readMoreTextWithStyle,
269+
toggleArea = toggleArea,
270+
)
283271
}
284272
}
285273
}
@@ -333,6 +321,77 @@ private fun CoreReadMoreText(
333321
}
334322
}
335323

324+
private fun AnnotatedString.Builder.appendCollapsedText(
325+
text: AnnotatedString,
326+
collapsedText: AnnotatedString,
327+
overflowText: String,
328+
onExpandedChange: ((Boolean) -> Unit)?,
329+
readMoreTextWithStyle: AnnotatedString,
330+
toggleArea: ToggleArea,
331+
) {
332+
if (collapsedText.isNotEmpty()) {
333+
append(collapsedText)
334+
append(overflowText)
335+
336+
if (toggleArea == ToggleArea.More) {
337+
withLink(
338+
LinkAnnotation.Clickable(tag = ReadMoreTag) {
339+
onExpandedChange?.invoke(true)
340+
},
341+
) {
342+
append(readMoreTextWithStyle)
343+
}
344+
} else {
345+
append(readMoreTextWithStyle)
346+
}
347+
} else {
348+
append(text)
349+
}
350+
}
351+
352+
private fun AnnotatedString.Builder.appendExpandedText(
353+
text: AnnotatedString,
354+
onExpandedChange: ((Boolean) -> Unit)?,
355+
readLessTextWithStyle: AnnotatedString,
356+
toggleArea: ToggleArea,
357+
) {
358+
append(text)
359+
if (readLessTextWithStyle.isNotEmpty()) {
360+
append(' ')
361+
if (toggleArea == ToggleArea.More) {
362+
withLink(
363+
LinkAnnotation.Clickable(tag = ReadLessTag) {
364+
onExpandedChange?.invoke(false)
365+
},
366+
) {
367+
append(readLessTextWithStyle)
368+
}
369+
} else {
370+
append(readLessTextWithStyle)
371+
}
372+
}
373+
}
374+
375+
private inline fun <R : Any> AnnotatedString.Builder.withContentsLink(
376+
hasLink: Boolean,
377+
linkInteractionListener: LinkInteractionListener?,
378+
block: AnnotatedString.Builder.() -> R,
379+
): R {
380+
return if (hasLink) {
381+
withLink(
382+
LinkAnnotation.Clickable(
383+
tag = ContentsTag,
384+
linkInteractionListener = linkInteractionListener,
385+
),
386+
block = block,
387+
)
388+
} else {
389+
block()
390+
}
391+
}
392+
393+
private fun AnnotatedString.hasLinks() = hasLinkAnnotations(0, length)
394+
336395
// ////////////////////////////////////
337396
// ReadMoreState
338397
// ////////////////////////////////////

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
@@ -462,7 +462,9 @@ private fun Item_Hyperlink(showMessage: (String) -> Unit) {
462462
withLink(
463463
LinkAnnotation.Clickable(
464464
tag = "TAG$index",
465-
styles = TextLinkStyles(style = SpanStyle(color = Color.Blue)),
465+
styles = TextLinkStyles(
466+
style = SpanStyle(color = Color.Blue),
467+
),
466468
) {
467469
showMessage("#TAG$index Clicked!")
468470
},

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
@@ -429,7 +429,9 @@ private fun Item_Hyperlink(showMessage: (String) -> Unit) {
429429
withLink(
430430
LinkAnnotation.Clickable(
431431
tag = "TAG$index",
432-
styles = TextLinkStyles(style = SpanStyle(color = Color.Blue)),
432+
styles = TextLinkStyles(
433+
style = SpanStyle(color = Color.Blue),
434+
),
433435
) {
434436
showMessage("#TAG$index Clicked!")
435437
},

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
@@ -448,7 +448,9 @@ private fun Item_Hyperlink(showMessage: (String) -> Unit) {
448448
withLink(
449449
LinkAnnotation.Clickable(
450450
tag = "TAG$index",
451-
styles = TextLinkStyles(style = SpanStyle(color = Color.Blue)),
451+
styles = TextLinkStyles(
452+
style = SpanStyle(color = Color.Blue),
453+
),
452454
) {
453455
showMessage("#TAG$index Clicked!")
454456
},

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)