Skip to content

Commit 3e28bba

Browse files
committed
feat(android): ordered list relayout on margin change optimization
1 parent af7834f commit 3e28bba

3 files changed

Lines changed: 37 additions & 17 deletions

File tree

android/src/main/java/com/swmansion/enriched/common/OrderedListMargins.kt

Lines changed: 37 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,44 +7,66 @@ import com.swmansion.enriched.common.spans.EnrichedOrderedListSpan
77
import com.swmansion.enriched.textinput.utils.getSafeSpanBoundaries
88

99
// Recomputes the shared marker column width for every ordered-list item.
10-
// Returns true when any item's column width changed, so callers can force a relayout.
1110
fun updateOrderedListColumnMargins(
1211
text: Spannable,
1312
paint: Paint,
1413
) {
1514
val spans = text.getSpans(0, text.length, EnrichedOrderedListSpan::class.java)
1615
val sortedSpans = spans.sortedBy { text.getSpanStart(it) }
1716

18-
var changed = false
17+
val changedLists = mutableSetOf<MutableList<EnrichedOrderedListSpan>>()
18+
var currentList = mutableListOf<EnrichedOrderedListSpan>()
19+
var currentListChanged = false
1920
var previousIndex = 0
2021
var highestIndex = 0
22+
2123
for (span in sortedSpans.reversed()) {
22-
val currentIndex = span.index
23-
if (currentIndex > previousIndex) {
24-
highestIndex = currentIndex
24+
if (span.index > previousIndex) {
25+
if (currentListChanged) {
26+
// we'll re-layout that list
27+
changedLists.add(currentList)
28+
}
29+
30+
// we entered a new distinct list
31+
currentList = mutableListOf()
32+
currentListChanged = false
33+
highestIndex = span.index
34+
}
35+
36+
currentList.add(span)
37+
if (span.updateColumnMargin(paint, highestIndex)) {
38+
currentListChanged = true
2539
}
26-
if (span.updateColumnMargin(paint, highestIndex)) changed = true
2740

28-
previousIndex = currentIndex
41+
previousIndex = span.index
2942
}
3043

31-
// Ordered list margins got updated, so we need to force a re-layout of that list.
32-
// Uses the same empty ParagraphStyle trick as EnrichedSpanWatcher.updateNextLineLayout.
33-
if (changed) {
34-
forceOrderedListRelayout(text, sortedSpans)
44+
if (currentListChanged) {
45+
changedLists.add(currentList)
46+
}
47+
48+
// A single empty ParagraphStyle over the whole list forces one re-layout of it.
49+
// Uses the same trick as EnrichedSpanWatcher.updateNextLineLayout.
50+
for (list in changedLists) {
51+
forceOrderedListRelayout(text, list)
3552
}
3653
}
3754

3855
private fun forceOrderedListRelayout(
3956
text: Spannable,
40-
sortedSpans: List<EnrichedOrderedListSpan>,
57+
listSpans: List<EnrichedOrderedListSpan>,
4158
) {
42-
if (sortedSpans.isEmpty()) return
59+
if (listSpans.isEmpty()) return
60+
61+
// Because the list was populated during a reversed() loop, the elements
62+
// are in descending order. last() is the start of the list, first() is the end.
63+
val start = text.getSpanStart(listSpans.last())
64+
val end = text.getSpanEnd(listSpans.first())
65+
66+
if (start < 0 || end < 0 || start > end) return
4367

4468
class EmptySpan : ParagraphStyle
4569

46-
val start = text.getSpanStart(sortedSpans.first())
47-
val end = text.getSpanEnd(sortedSpans.last())
4870
val (safeStart, safeEnd) = text.getSafeSpanBoundaries(start, end)
4971
text.getSpans(safeStart, safeEnd, EmptySpan::class.java).forEach { text.removeSpan(it) }
5072
text.setSpan(EmptySpan(), safeStart, safeEnd, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)

android/src/main/java/com/swmansion/enriched/textinput/EnrichedTextInputView.kt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import android.text.Editable
1313
import android.text.InputType
1414
import android.text.Spannable
1515
import android.text.SpannableString
16-
import android.text.Spanned
1716
import android.util.AttributeSet
1817
import android.util.Log
1918
import android.util.Patterns

android/src/main/java/com/swmansion/enriched/textinput/styles/ListStyles.kt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import android.text.Editable
44
import android.text.Spannable
55
import android.text.SpannableStringBuilder
66
import android.text.Spanned
7-
import android.text.style.ParagraphStyle
87
import com.swmansion.enriched.common.EnrichedConstants
98
import com.swmansion.enriched.common.EnrichedSpanFlags
109
import com.swmansion.enriched.common.updateOrderedListColumnMargins

0 commit comments

Comments
 (0)