mirror of
https://github.com/Tencent/QMUI_Android.git
synced 2026-10-17 04:31:16 +08:00
bugfix: word break issue.
This commit is contained in:
+1
-1
@@ -159,7 +159,7 @@ class QDQQFaceUsageFragment : BaseFragment() {
|
||||
}
|
||||
|
||||
private fun initData() {
|
||||
val textParser: TextParser = EmojiTextParser(QDQQFaceManager.getInstance())
|
||||
val textParser: TextParser = EmojiTextParser(QDQQFaceManager.getInstance()) { true }
|
||||
mMarqueeTypeView1!!.fadeWidth = QMUIDisplayHelper.dp2px(context, 40).toFloat()
|
||||
mMarqueeTypeView1!!.textParser = textParser
|
||||
mMarqueeTypeView1!!.text = "🙃🙃🙃🙃飘呀飘呀飘呀飘呀飘呀飘呀飘呀飘呀飘呀飘呀飘呀飘呀飘呀飘呀飘呀飘呀飘呀飘呀飘呀飘呀飘呀飘呀飘呀飘呀飘呀飘呀这是一行很长很长[微笑][微笑][微笑][微笑]的文本,但是[微笑][微笑][微笑][微笑]只能单行显示"
|
||||
|
||||
@@ -17,7 +17,6 @@ package com.qmuiteam.qmui.type
|
||||
|
||||
import android.graphics.Canvas
|
||||
import androidx.core.util.Pools
|
||||
import com.qmuiteam.qmui.type.TypeEnvironment
|
||||
import com.qmuiteam.qmui.type.element.BreakWordLineElement
|
||||
import com.qmuiteam.qmui.type.element.Element
|
||||
import com.qmuiteam.qmui.type.element.NextParagraphElement
|
||||
@@ -86,7 +85,7 @@ class Line private constructor() {
|
||||
}
|
||||
}
|
||||
|
||||
fun handleWordBreak(environment: TypeEnvironment?, shouldHandleWordBreak: Boolean): List<Element>? {
|
||||
fun handleWordBreak(environment: TypeEnvironment, shouldHandleWordBreak: Boolean): List<Element>? {
|
||||
if (mElements.size == 0 || !shouldHandleWordBreak) {
|
||||
return null
|
||||
}
|
||||
@@ -96,7 +95,8 @@ class Line private constructor() {
|
||||
val back: MutableList<Element> = LinkedList()
|
||||
if (last.wordPart == Element.WORD_PART_WHOLE) {
|
||||
if (last.lineBreakType == Element.LINE_BREAK_TYPE_NOT_END ||
|
||||
next != null && next.lineBreakType == Element.LINE_BREAK_TYPE_NOT_START) {
|
||||
next != null && next.lineBreakType == Element.LINE_BREAK_TYPE_NOT_START
|
||||
) {
|
||||
mElements.removeAt(lastIndex)
|
||||
back.add(last)
|
||||
}
|
||||
@@ -109,7 +109,7 @@ class Line private constructor() {
|
||||
back.add(last)
|
||||
mElements.removeAt(lastIndex)
|
||||
lastIndex--
|
||||
val min = Math.max(0, lastIndex - 30) // try 30 letter.
|
||||
val min = 0.coerceAtLeast(lastIndex - environment.workBreakMaxTryLength)
|
||||
var find = false
|
||||
while (lastIndex > min) {
|
||||
val el = mElements[lastIndex]
|
||||
@@ -119,10 +119,17 @@ class Line private constructor() {
|
||||
} else if (el.lineBreakType == Element.LINE_BREAK_WORD_BREAK_ALLOWED) {
|
||||
// TODO what if environment had changed after break? the measure may be wrong
|
||||
val b = BreakWordLineElement()
|
||||
b.measure(environment!!)
|
||||
add(b)
|
||||
find = true
|
||||
break
|
||||
b.measure(environment)
|
||||
val backWidth = back.sumOf { it.measureWidth }
|
||||
if (backWidth >= b.measureWidth) {
|
||||
find = true
|
||||
add(b)
|
||||
break
|
||||
} else {
|
||||
back.add(0, el)
|
||||
mElements.removeAt(lastIndex)
|
||||
lastIndex--
|
||||
}
|
||||
} else {
|
||||
back.add(0, el)
|
||||
mElements.removeAt(lastIndex)
|
||||
@@ -139,7 +146,7 @@ class Line private constructor() {
|
||||
return null
|
||||
}
|
||||
for (el in back) {
|
||||
contentWidth = (contentWidth -el.measureWidth).toInt()
|
||||
contentWidth -= el.measureWidth
|
||||
}
|
||||
return back
|
||||
}
|
||||
@@ -171,8 +178,9 @@ class Line private constructor() {
|
||||
for (i in 1 until mElements.size) {
|
||||
val el = mElements[i]
|
||||
if (el.visible != Element.GONE &&
|
||||
(el.wordPart == Element.WORD_PART_WHOLE ||
|
||||
el.wordPart == Element.WORD_PART_START)) {
|
||||
(el.wordPart == Element.WORD_PART_WHOLE ||
|
||||
el.wordPart == Element.WORD_PART_START)
|
||||
) {
|
||||
ret++
|
||||
}
|
||||
}
|
||||
@@ -209,7 +217,8 @@ class Line private constructor() {
|
||||
for (i in mElements.indices) {
|
||||
val el = mElements[i]
|
||||
if (i > 0 && (el.wordPart == Element.WORD_PART_WHOLE
|
||||
|| el.wordPart == Element.WORD_PART_START)) {
|
||||
|| el.wordPart == Element.WORD_PART_START)
|
||||
) {
|
||||
x += addSpace
|
||||
mElements[i - 1].nextGapWidth = addSpace
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@ class LineLayout {
|
||||
var moreUnderlineColor = Color.TRANSPARENT
|
||||
var moreBgColor = 0
|
||||
var moreUnderlineHeight = 0
|
||||
var moreTextFixAtEnd: Boolean = true
|
||||
var typeModel: TypeModel? = null
|
||||
var shouldHandleWordBreak: Boolean = true
|
||||
|
||||
@@ -234,7 +235,12 @@ class LineLayout {
|
||||
}
|
||||
lastLine.layout(env, dropLastIfSpace, true)
|
||||
if (moreElement != null) {
|
||||
moreElement.x = lastLine.x + lastLine.widthLimit - moreElement.measureWidth
|
||||
if(moreTextFixAtEnd){
|
||||
moreElement.x = lastLine.x + lastLine.widthLimit - moreElement.measureWidth
|
||||
}else{
|
||||
moreElement.x = lastLine.contentWidth - moreElement.measureWidth
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -72,7 +72,7 @@ class TypeEnvironment {
|
||||
private val mCustomProp: SparseArray<Any?> = SparseArray()
|
||||
private val mStack = SparseArray<Stack<Any?>>()
|
||||
|
||||
val layoutExcludeAreas = arrayListOf<Rect>()
|
||||
var workBreakMaxTryLength: Int = 10
|
||||
|
||||
var lineSpace = 0
|
||||
|
||||
|
||||
@@ -22,7 +22,10 @@ import com.qmuiteam.qmui.type.element.NextParagraphElement
|
||||
import com.qmuiteam.qmui.type.element.TextElement
|
||||
import java.util.*
|
||||
|
||||
class EmojiTextParser(private val emojiProvider: EmojiResourceProvider) : TextParser {
|
||||
class EmojiTextParser(
|
||||
private val emojiProvider: EmojiResourceProvider,
|
||||
private val wordBreakChecker: (c: Char) -> Boolean
|
||||
) : TextParser {
|
||||
|
||||
override fun parse(text: CharSequence?): TypeModel? {
|
||||
if(text == null || text.isEmpty()){
|
||||
@@ -105,7 +108,7 @@ class EmojiTextParser(private val emojiProvider: EmojiResourceProvider) : TextPa
|
||||
i += charCount - 1
|
||||
}
|
||||
}
|
||||
ParserHelper.handleWordPart(c, last, tmp!!)
|
||||
ParserHelper.handleWordPart(c, last, tmp!!, wordBreakChecker)
|
||||
index++
|
||||
if (first == null) {
|
||||
first = tmp
|
||||
|
||||
@@ -23,16 +23,20 @@ object ParserHelper {
|
||||
return c in 'a'..'z' || c in 'A'..'Z' || c in '0'..'9'
|
||||
}
|
||||
|
||||
fun handleWordPart(c: Char, prev: Element?, curr: Element) {
|
||||
fun handleWordPart(c: Char, prev: Element?, curr: Element, wordBreakChecker: (c: Char) -> Boolean) {
|
||||
if (isEnglishLetterOrNumber(c)) {
|
||||
if (prev == null || prev.wordPart == Element.WORD_PART_WHOLE || prev.wordPart == Element.WORD_PART_END) {
|
||||
curr.wordPart = Element.WORD_PART_START
|
||||
} else {
|
||||
curr.wordPart = Element.WORD_PART_MIDDLE
|
||||
if(wordBreakChecker(c)){
|
||||
curr.lineBreakType = Element.LINE_BREAK_WORD_BREAK_ALLOWED
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (prev != null && prev.wordPart == Element.WORD_PART_MIDDLE) {
|
||||
prev.wordPart = Element.WORD_PART_END
|
||||
prev.lineBreakType = Element.LINE_BREAK_TYPE_NORMAL
|
||||
}
|
||||
curr.wordPart = Element.WORD_PART_WHOLE
|
||||
}
|
||||
|
||||
@@ -22,11 +22,15 @@ import com.qmuiteam.qmui.type.element.TextElement
|
||||
import com.qmuiteam.qmui.type.parser.ParserHelper.handleWordPart
|
||||
import java.util.*
|
||||
|
||||
class PlainTextParser : TextParser {
|
||||
class PlainTextParser(
|
||||
private val wordBreakChecker: (c: Char) -> Boolean
|
||||
) : TextParser {
|
||||
|
||||
companion object {
|
||||
val instance by lazy {
|
||||
PlainTextParser()
|
||||
PlainTextParser {
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,7 +62,7 @@ class PlainTextParser : TextParser {
|
||||
tmp = TextElement(text.subSequence(i, i + charCount), index, i)
|
||||
i += charCount - 1
|
||||
}
|
||||
handleWordPart(c, last, tmp)
|
||||
handleWordPart(c, last, tmp, wordBreakChecker)
|
||||
index++
|
||||
if (first == null) {
|
||||
first = tmp
|
||||
|
||||
Reference in New Issue
Block a user