项目需要展示标签列表,并且要显示文本溢出效果(统计并显示隐藏的标签个数)。Compose 实现这个效果还是很简单的,Compose 中 Text 的 onTextLayout
参数是 Text 计算布局时的回调,包含段落信息、文本大小、基线和其他详细信息。这个回调可用来向文本添加额外的装饰或功能。例如,围绕文本绘制选择。
onTextLayout
回调的参数是 TextLayoutResult
对象,它包含有很多 Text 的详细信息,这里用到的主要是 hasVisualOverflow
和 getLineEnd
(判断是否发生了文本溢出,获取某行结束的偏移量)。
下图是实现的效果:
如下是实现该效果的代码:
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import cn.itmob.catalog.compose.ui.theme.ComposeCatalogTheme
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
ComposeCatalogTheme {
// A surface container using the 'background' color from the theme
Surface(
modifier = Modifier
.fillMaxSize()
.padding(16.dp),
color = MaterialTheme.colorScheme.background
) {
Column(verticalArrangement = Arrangement.Center) {
Greeting(
arrayOf(
"Android",
"IOS",
"Java",
"Kotlin",
"Go",
"Dart",
"JS",
"TypeScript",
"C",
"CPP",
"Lua",
"PHP"
)
)
}
}
}
}
}
}
@Composable
fun Greeting(contacts: Array<String>) {
var overflowedText by remember { mutableStateOf("") }
var overflowedTextCount by remember { mutableStateOf(0) }
var overflowedTagsCount by remember { mutableStateOf(0) }
val contactsStr = contacts.joinToString(", ")
Column {
Row {
Text(
text = "Tags: $contactsStr",
modifier = Modifier
.fillMaxWidth()
.weight(1f),
overflow = TextOverflow.Ellipsis,
maxLines = 1,
onTextLayout = { layoutResult ->
if (layoutResult.hasVisualOverflow) {
val lineEnd = layoutResult.getLineEnd(lineIndex = 0, visibleEnd = true)
contactsStr.substring(lineEnd).let {
overflowedTagsCount = it.split(", ").count()
overflowedTextCount = it.length
overflowedText = it
}
}
}
)
if (overflowedTagsCount > 0) {
Text(
modifier = Modifier
.clip(RoundedCornerShape(100))
.background(Color.LightGray)
.alpha(0.5f)
.padding(horizontal = 4.dp),
text = overflowedTagsCount.toString()
)
}
}
Spacer(Modifier.height(16.dp))
Text("Overflowed Count: $overflowedTextCount")
Spacer(Modifier.height(16.dp))
Text("Overflowed Text: $overflowedText")
}
}