From 273495295bd48deff701ca88cf42fe24888ad599 Mon Sep 17 00:00:00 2001 From: cgspine Date: Tue, 1 Mar 2022 16:10:02 +0800 Subject: [PATCH] bugfix: fix indent issues. --- .../qqface/QDQQFaceUsageFragment.kt | 2 +- .../qmuiteam/qmui/type/LineIndentHandler.kt | 76 ++++++++++--------- .../java/com/qmuiteam/qmui/type/LineLayout.kt | 14 ++-- 3 files changed, 49 insertions(+), 43 deletions(-) diff --git a/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/components/qqface/QDQQFaceUsageFragment.kt b/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/components/qqface/QDQQFaceUsageFragment.kt index 683d9b5f..d2ca7da7 100644 --- a/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/components/qqface/QDQQFaceUsageFragment.kt +++ b/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/components/qqface/QDQQFaceUsageFragment.kt @@ -212,7 +212,7 @@ class QDQQFaceUsageFragment : BaseFragment() { mLineType2!!.text = content2 val pairs = arrayListOf>() - val pattern = Pattern.compile("([a-z]\\.)") + val pattern = Pattern.compile("([a-z]+\\.)") val matcher = pattern.matcher(content2) while (matcher.find()){ pairs.add(matcher.start() to matcher.end() - 1) diff --git a/type/src/main/java/com/qmuiteam/qmui/type/LineIndentHandler.kt b/type/src/main/java/com/qmuiteam/qmui/type/LineIndentHandler.kt index c457df23..4048425f 100644 --- a/type/src/main/java/com/qmuiteam/qmui/type/LineIndentHandler.kt +++ b/type/src/main/java/com/qmuiteam/qmui/type/LineIndentHandler.kt @@ -3,53 +3,55 @@ package com.qmuiteam.qmui.type import com.qmuiteam.qmui.type.element.Element interface LineIndentHandler { - fun getIndent(typeModel: TypeModel, firstElement: Element): Int + fun reset() + fun processIndent(typeModel: TypeModel, firstElement: Element, newParagraph: Boolean): Int } -class SerialLineIndentHandler(serials: List>): LineIndentHandler { +class SerialLineIndentHandler( + serials: List>, + private val followIndentForNewParagraphIfNeeded: Boolean = false): LineIndentHandler { private val sorted = serials.sortedBy { it.first } - var prevIndexCache = -1 + var currentIntend = 0 + private var pendingCalculatePair: Pair? = null + var nextIndex = 0 - override fun getIndent(typeModel: TypeModel, firstElement: Element): Int { - if(sorted.isEmpty()){ - return 0 - } - - if(prevIndexCache >= 0 && firstElement.index > prevIndexCache){ - // check fast path - if(prevIndexCache == sorted.size - 1 || sorted[prevIndexCache + 1].first > firstElement.index){ - return calculateIndent(typeModel, firstElement, prevIndexCache) - } else if(prevIndexCache + 1 == sorted.size - 1 || sorted[prevIndexCache + 2].first > firstElement.index) { - prevIndexCache += 1 - return calculateIndent(typeModel, firstElement, prevIndexCache) - }else{ - prevIndexCache = -1 - } - } - - val nextIndex = sorted.indexOfFirst { it.first > firstElement.index } - if(nextIndex == 0){ - return 0 - } - val prevIndex = if(nextIndex < 0) sorted.size - 1 else nextIndex - 1 - prevIndexCache = prevIndex - return calculateIndent(typeModel, firstElement, prevIndex) + override fun reset() { + currentIntend = 0 + nextIndex = 0 } - private fun calculateIndent(typeModel: TypeModel, firstElement: Element, index: Int): Int{ - val cur = sorted[index] - if(firstElement.index <= cur.second){ - return 0 + override fun processIndent(typeModel: TypeModel, firstElement: Element, newParagraph: Boolean): Int { + if(newParagraph){ + val pair = sorted.find { it.first == firstElement.index } + if(pair != null){ + currentIntend = 0 + }else if(!followIndentForNewParagraphIfNeeded){ + currentIntend = 0 + } else { + // make sure it's calculated. + pendingCalculatePair?.let { + var indent = 0 + for(i in it.first until it.second + 1){ + indent += typeModel[i]?.measureWidth ?: 0 + } + currentIntend = indent + } + } + pendingCalculatePair = pair + }else{ + pendingCalculatePair?.let { + var indent = 0 + for(i in it.first until it.second + 1){ + indent += typeModel[i]?.measureWidth ?: 0 + } + currentIntend = indent + } + pendingCalculatePair = null } - - var indent = 0 - for(i in cur.first until cur.second + 1){ - indent += typeModel[i]?.measureWidth ?: 0 - } - return indent + return currentIntend } } \ No newline at end of file diff --git a/type/src/main/java/com/qmuiteam/qmui/type/LineLayout.kt b/type/src/main/java/com/qmuiteam/qmui/type/LineLayout.kt index 2d1c4c8c..a5b479b6 100644 --- a/type/src/main/java/com/qmuiteam/qmui/type/LineLayout.kt +++ b/type/src/main/java/com/qmuiteam/qmui/type/LineLayout.kt @@ -58,13 +58,14 @@ class LineLayout { exactlyHeightMaxLine = Int.MAX_VALUE env.clear() release() + lineIndentHandler?.reset() if (typeModel == null) { return } var element: Element? = typeModel!!.firstElement() var line = Line.acquire() var y = 0 - val indent = element?.let { lineIndentHandler?.getIndent(typeModel!!, it) } ?: 0 + val indent = element?.let { lineIndentHandler?.processIndent(typeModel!!, it, true) } ?: 0 line.init(indent, y, env.widthLimit - indent) fun addLineAndHandleMaxLineAndNextY(line: Line, isParagraphEndLine: Boolean){ @@ -94,13 +95,15 @@ class LineLayout { addLineAndHandleMaxLineAndNextY(line, true) if (canInterrupt()) { handleEllipse(env,true) + totalLineCount = mLines.size return } - line = createNewLine(env, element.next, y) + line = createNewLine(env, element.next, y, true) } else if (line.contentWidth + element.measureWidth >= line.widthLimit) { if (mLines.size == 0 && line.size == 0) { // the width is too small. line.release() + totalLineCount = mLines.size return } val back = line.handleWordBreak(env, shouldHandleWordBreak) @@ -108,11 +111,12 @@ class LineLayout { addLineAndHandleMaxLineAndNextY(line, false) if (canInterrupt()) { + totalLineCount = mLines.size handleEllipse(env,true) return } - line = createNewLine(env, back?.firstOrNull() ?: element, y) + line = createNewLine(env, back?.firstOrNull() ?: element, y, false) if (back != null && back.isNotEmpty()) { for (el in back) { line.add(el) @@ -144,9 +148,9 @@ class LineLayout { } } - private fun createNewLine(env: TypeEnvironment, firstElement: Element?, y: Int): Line { + private fun createNewLine(env: TypeEnvironment, firstElement: Element?, y: Int, newParagraph: Boolean): Line { val line = Line.acquire() - val indent = firstElement?.let { lineIndentHandler?.getIndent(typeModel!!, it) } ?: 0 + val indent = firstElement?.let { lineIndentHandler?.processIndent(typeModel!!, it, newParagraph) } ?: 0 line.init(indent, y, env.widthLimit - indent) return line }