@@ -7,44 +7,66 @@ import com.swmansion.enriched.common.spans.EnrichedOrderedListSpan
77import 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.
1110fun 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
3855private 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 )
0 commit comments