mirror of
https://github.com/divkit/divkit.git
synced 2026-06-06 20:07:59 +00:00
Fix text ranges background drowing
commit_hash:b07fb3fe3311175249c2b6ad5289d74116258861
This commit is contained in:
+37
-21
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+19
-6
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -110,7 +110,7 @@ open class EllipsizedTextView @JvmOverloads constructor(
|
||||
}
|
||||
|
||||
override fun getText(): CharSequence {
|
||||
return originalText ?: ""
|
||||
return ellipsizedText ?: originalText ?: ""
|
||||
}
|
||||
|
||||
private fun setTextInternal(text: CharSequence?) {
|
||||
|
||||
Reference in New Issue
Block a user