Fix text ranges background drowing

commit_hash:b07fb3fe3311175249c2b6ad5289d74116258861
This commit is contained in:
grechka62
2025-10-22 12:02:44 +03:00
parent 2d34ab715f
commit fd2fead8ef
3 changed files with 57 additions and 28 deletions
@@ -13,10 +13,23 @@ internal class DivTextRangesBackgroundHelper(
val resolver: ExpressionResolver,
) {
private var spans = ArrayList<DivBackgroundSpan>()
internal fun invalidateSpansCache() = spans.clear()
internal fun addBackgroundSpan(span: DivBackgroundSpan) = spans.add(span)
internal fun hasBackgroundSpan(): Boolean = spans.isNotEmpty()
private val spans = ArrayList<DivBackgroundSpan>()
private val ellipsisSpans = ArrayList<DivBackgroundSpan>()
internal fun invalidateSpansCache(inEllipsis: Boolean) {
if (inEllipsis) {
ellipsisSpans.clear()
} else {
spans.clear()
}
}
internal fun addBackgroundSpan(span: DivBackgroundSpan, inEllipsis: Boolean) {
if (inEllipsis) {
ellipsisSpans.add(span)
} else {
spans.add(span)
}
}
internal fun hasBackgroundSpan(): Boolean = spans.isNotEmpty() || ellipsisSpans.isNotEmpty()
internal fun hasSameSpan(text: CharSequence, backgroundSpan: DivBackgroundSpan, start: Int, end: Int): Boolean {
val spannedText = text as? Spannable ?: return false
return spans.any { span ->
@@ -47,26 +60,29 @@ internal class DivTextRangesBackgroundHelper(
}
fun draw(canvas: Canvas, text: Spanned, layout: Layout) {
spans.forEach { span ->
val spanStart = text.getSpanStart(span)
val spanEnd = text.getSpanEnd(span)
val startLine = layout.getLineForOffset(spanStart)
val endLine = layout.getLineForOffset(spanEnd)
spans.forEach { applySpan(it, canvas, text, layout) }
ellipsisSpans.forEach { applySpan(it, canvas, text, layout) }
}
val startOffset = layout.getPrimaryHorizontal(spanStart).toInt()
val endOffset = layout.getPrimaryHorizontal(spanEnd).toInt()
private fun applySpan(span: DivBackgroundSpan, canvas: Canvas, text: Spanned, layout: Layout) {
val spanStart = text.getSpanStart(span)
val spanEnd = text.getSpanEnd(span)
val startLine = layout.getLineForOffset(spanStart)
val endLine = layout.getLineForOffset(spanEnd)
when (span.background) {
is DivTextRangeBackground.Cloud -> {
cloudBackgroundRenderer.draw(canvas, layout, startLine, endLine, startOffset, endOffset,
span.border, span.background)
}
val startOffset = layout.getPrimaryHorizontal(spanStart).toInt()
val endOffset = layout.getPrimaryHorizontal(spanEnd).toInt()
else -> {
val renderer = if (startLine == endLine) singleLineRenderer else multiLineRenderer
renderer.draw(canvas, layout, startLine, endLine, startOffset, endOffset,
span.border, span.background)
}
when (span.background) {
is DivTextRangeBackground.Cloud -> {
cloudBackgroundRenderer.draw(canvas, layout, startLine, endLine, startOffset, endOffset,
span.border, span.background)
}
else -> {
val renderer = if (startLine == endLine) singleLineRenderer else multiLineRenderer
renderer.draw(canvas, layout, startLine, endLine, startOffset, endOffset,
span.border, span.background)
}
}
}
@@ -112,7 +112,9 @@ internal class SpannedTextBuilder @Inject constructor(
ellipsis.ranges,
ellipsis.images,
ellipsis.actions,
textConsumer)
textConsumer,
inEllipsis = true
)
}
private fun buildText(
@@ -123,7 +125,8 @@ internal class SpannedTextBuilder @Inject constructor(
ranges: List<DivText.Range>?,
images: List<DivText.Image>?,
actions: List<DivAction>?,
textConsumer: TextConsumer? = null
textConsumer: TextConsumer? = null,
inEllipsis: Boolean = false,
): Spanned {
val context = textView.context
val divView = bindingContext.divView
@@ -142,7 +145,7 @@ internal class SpannedTextBuilder @Inject constructor(
(textView as? DivLineHeightTextView)?.apply {
clearImageSpans()
textRoundedBgHelper?.invalidateSpansCache()
textRoundedBgHelper?.invalidateSpansCache(inEllipsis)
}
spans.forEach { span ->
@@ -160,7 +163,16 @@ internal class SpannedTextBuilder @Inject constructor(
val start = range.start.evaluate(resolver).toIntSafely().coerceAtMost(textLength)
val end = range.end?.evaluate(resolver)?.toIntSafely()?.coerceAtMost(textLength) ?: textLength
addActionSpan(bindingContext, textView, spannedText, start, end, range.actions)
addDecorationSpan(bindingContext, textView, spannedText, start, end, range.border, range.background)
addDecorationSpan(
bindingContext,
textView,
spannedText,
start,
end,
range.border,
range.background,
inEllipsis
)
}
}
@@ -467,7 +479,8 @@ internal class SpannedTextBuilder @Inject constructor(
start: Int,
end: Int,
border: DivTextRangeBorder?,
background: DivTextRangeBackground?
background: DivTextRangeBackground?,
inEllipsis: Boolean,
) {
if (border == null && background == null) return
@@ -476,7 +489,7 @@ internal class SpannedTextBuilder @Inject constructor(
if (textView is DivLineHeightTextView &&
!textView.hasBackgroundSpan(spannedText, backgroundSpan, start, end, resolver)) {
spannedText.setSpan(backgroundSpan, start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
textView.textRoundedBgHelper?.addBackgroundSpan(backgroundSpan)
textView.textRoundedBgHelper?.addBackgroundSpan(backgroundSpan, inEllipsis)
}
}
@@ -110,7 +110,7 @@ open class EllipsizedTextView @JvmOverloads constructor(
}
override fun getText(): CharSequence {
return originalText ?: ""
return ellipsizedText ?: originalText ?: ""
}
private fun setTextInternal(text: CharSequence?) {