之前的文章Android Oreo--Autosizing TextViews自适应TextView介绍了Android 8.0的一个新特性文本字体大小自适应,是一个非常实用的工具,但是在Jetpack Compose却无法使用,本文就在Jetpack Compose中研究下怎么实现文本大小自适应。
先看下最终的效果:
demo.gif
直接上代码,不解释,因为不难理解:
AutoSizeTextView.kt
package com.zzh.eden.stark.demo.ui
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.drawWithContent
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.sp
@Composable
fun AutoSizeTextView(str: MutableState<String> = mutableStateOf(""), defaultSizeSp: Int = 15, maxLines: Int = 1) {
var readyToDraw: Boolean by remember { mutableStateOf(false) }
// var size = MaterialTheme.typography.bodyMedium
// var tvStyle by remember { mutableStateOf(size) }
var fontSize by remember { mutableStateOf(defaultSizeSp.sp) }
Text(text = str.value,
maxLines = maxLines,
fontSize = fontSize,
overflow = TextOverflow.Ellipsis,
// style = tvStyle, // 这个方式也能动态调整字体大小,可以放开注释看下效果
modifier = Modifier
.drawWithContent {
if (readyToDraw) drawContent()
},
onTextLayout = { textLayoutResult ->
if (textLayoutResult.didOverflowHeight) {
// 下面两行是两个方式,都可行
// tvStyle = (tvStyle.copy(fontSize = tvStyle.fontSize * 0.95))
fontSize = fontSize * 0.95
} else {
readyToDraw = true
}
}
)
}
MainActivity.kt
package com.zzh.eden.stark.demo
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Button
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp
import com.zzh.eden.stark.demo.ui.AutoSizeTextView
import com.zzh.eden.stark.demo.ui.theme.StarkdemoTheme
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
StarkdemoTheme {
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
delTest()
}
}
}
}
@Composable
fun delTest() {
val context = LocalContext.current
var clickCnt: MutableState<Int> = remember { mutableStateOf(0) }
var text: MutableState<String> = remember { mutableStateOf("click cnt=${clickCnt}") }
Column(
modifier = Modifier
.fillMaxWidth()
.fillMaxHeight(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Button(
onClick = {
clickCnt.value += 1
StringBuilder().apply {
for (tmpI in 1..clickCnt.value) {
append("x")
}
text.value = "click cnt=${clickCnt}_${this}"
}
}) {
AutoSizeTextView(text)
}
}
}
}
参考文献: