我在Jetpack compose中看到一個奇怪的影像閃爍問題。這是一副簡單的兩張牌,上面的影像在螢屏外被影片化以顯示第二張牌。第二張牌在一秒鐘內顯示正常,然后第一張牌的影像在螢屏上閃爍。我試著用Coil、Fresco和Glide,它們的表現都一樣。
import androidx.activity.compose.setContent
import androidx.activity.viewModels
import androidx.compose.animation.core.Animatable
import androidx.compose. foundation.Image
import androidx.compose. foundation.background
import androidx.compose. foundation.clickable
import androidx.compose.foundation.layout.*.
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.livedata.observeAsState
importandroidx.compose.runtime.remember。
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier
importandroidx.compose.ui.graphics.Color。
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.dp
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import coil.compose.rememberImagePainter
import kotlinx.coroutines.delay
import kotlinx.coroutines. launch
import kotlin.math.roundToInt
class MainViewModel : ViewModel(){
var images = MutableLiveData(listOf(
"https://images.pexels.com/photos/212286/pexels-photo-212286.jpeg?auto=compress&cs=tinysrgb&dpr=1& w=500"。
"https://images.pexels.com/photos/163016/crash-test-collision-60-km-h-distraction-163016.jpeg?auto=compress&cs=tinysrgb&dpr=1& w=500"。
"https://images.pexels.com/photos/1366944/pexels-photo-1366944.jpeg?auto=compress&cs=tinysrgb&dpr=1& w=500"。
"https://images.pexels.com/photos/5878501/pexels-photo-5878501.jpeg?auto=compress&cs=tinysrgb&dpr=1& w=500"。
"https://images.pexels.com/photos/3846022/pexels-photo-3846022.jpeg?auto=compress&cs=tinysrgb&dpr=1& w=500"。
))
}
class MainActivity : ComponentActivity(){
private val model by viewModels<MainViewModel>()
override fun onCreate(sedInstanceState: Bundle? ){
super.onCreate(s savedInstanceState)
setContent {
MainScreen(model)
}
}
}
@Composable
fun MainScreen(model: MainViewModel) {
val images: List<String> by model.images.observeAsState(listOf()
盒子(
modifier = Modifier.fillMaxSize()
) {
images?.take(2).reversed().forEach {
Card(url = it) {
val d = model.images.value?.toMutableList()
d?.let {
it.removeFirst()
model.images.value = it
}
}
}
}
}
@Composable
fun Card(
網址。String,
advance: ()-> Unit = {},
){
val coroutineScope = rememberCoroutineScope()
var offsetX = remember(url) { Animatable(0f) }
Box(
修改器 = 修改器
.offset { IntOffset(offsetX.value.roundToInt(), 0) }
.fillMaxSize()
.background(color = Color.White)
.clickable {
coroutineScope.launch {
offsetX.animateTo(
targetValue = 3000F 400)
推進()
}
}
) {
影像(
painter = rememberImagePainter(
data = url,
),
contentDescription = null,
修改器 = 修改器
.size(400.dp, 400.dp)
)
}
}

我也把它扔到了github上,以防有人想試試。 https://github.com/studentjet/learncompose
uj5u.com熱心網友回復:
問題是這樣的:你有兩個卡片視圖。在洗掉頂層卡片后,compose重用它們并以新的資料更新它們。而當頂層卡片加載第二張圖片時,它仍然顯示第一張圖片。
你可以禁用快取,但在這種情況下,圖片仍然會閃現,因為它將首先顯示一個空位。相反,你需要讓第二張卡的視圖重新用于第一張卡。
要做到這一點,你必須進入Compose布局的最深層次。SubcomposeLayout。它被用來構建LazyColumn,而且它是唯一一個可以為可組合的鍵指定的地方,以便將來用subcompose。
對你的代碼也有一些非主題性的建議。
你可以使用
mutableStateListOf而不是LiveData<List>:更新它將更容易。你不需要運行兩個coroutine,并且用
delay(400)來等待影片的完成。animateTo也是一個暫停函式,它將在影片結束時將控制權交給coroutine,所以你可以在之后立即移除該元素。
@Composable
fun MainScreen(model: MainViewModel) {
val images = model.images
SubcomposeLayout(
modifier = Modifier.fillMaxSize()
) { constraints ->
val placeables = images.take(2).reversed() { image ->
// this is essential line. 我正在使用`image`作為`subcompose`的id。
//所以內容在洗掉一個專案后會被重新使用。
subcompose(image) {
Card(url = image) {
model.images.removeFirst()
}
}.first().measure( constraints)
}
layout()
width = placeables.maxOf { it.width },
height = placeables.maxOf { it.height },
) {
placeables.forEach {
it.place(IntOffset.Zero)
}
}
}
}
class MainViewModel : ViewModel(){
var images = mutableStateListOf(
"https://images.pexels.com/photos/1366944/pexels-photo-1366944.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"/span>。
"https://images.pexels.com/photos/163016/crash-test-collision-60-km-h-distraction-163016.jpeg?auto=compress&cs=tinysrgb&dpr=1& w=500"。
"https://images.pexels.com/photos/212286/pexels-photo-212286.jpeg?auto=compress&cs=tinysrgb&dpr=1& w=500"。
"https://images.pexels.com/photos/3846022/pexels-photo-3846022.jpeg?auto=compress&cs=tinysrgb&dpr=1& w=500"。
"https://images.pexels.com/photos/5878501/pexels-photo-5878501.jpeg?auto=compress&cs=tinysrgb&dpr=1& w=500"。
)
}
@Composable
fun Card(
網址。String,
advance: () -> Unit = {},
) {
val coroutineScope = rememberCoroutineScope()
var offsetX = remember(url) { Animatable(0f) }
Box(
修改器 = 修改器
.offset { IntOffset(offsetX.value.roundToInt(), 0) }
.background(color = Color.White)
.可點擊 {
coroutineScope.launch {
offsetX.animateTo(
targetValue = 3000F,
animationSpec = tween(1000)
)
推進()
}
}
) {
val painter = rememberImagePainter(
data = url,
)
println("$url ${painter.state}")
影像(
painter = 畫家。
contentDescription = null。
修改器 = 修改器
.size(400.dp, 400.dp)
)
}
}

轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/313053.html
標籤:
