Tutorial Jetpack Compose: Replikasi Aplikasi Audio Dribbble Bagian 2
Menerapkan UI yang sepenuhnya disesuaikan dengan animasi kompleks: Action Panel
Di Exyte kami mencoba untuk berkontribusi pada sumber terbuka sebanyak yang kami bisa, mulai dari merilis pustaka dan komponen hingga menulis artikel dan tutorial. Salah satu jenis tutorial yang kami lakukan adalah mereplikasi — mengambil komponen UI yang kompleks, mengimplementasikannya menggunakan kerangka kerja baru, dan menulis tutorial bersama. Kami mulai dengan SwiftUI beberapa tahun yang lalu, tetapi kali ini kami akhirnya terjun ke Android, menggunakan kerangka UI deklaratif Google: Jetpack Compose.
Ini adalah artikel kedua dari seri Replikasi dribbble. Posting sebelumnya menunjukkan penerapan bilah audio animasi lebar dinamis . Yang ini akan fokus pada replikasi Panel Tindakan.
Menghancurkannya
Pertimbangkan bagaimana panel dirancang. Mari kita lihat panel ini dengan animasi gerak lambat:
Di setiap item daftar komentar, kami memiliki dua elemen:
CommentListItemyang menampilkan informasi komentar.ActionPanel, panel kecil dengan tombol aksi komentar di dalamnya. Itu berguling ketikaCommentListItempengguna mengklik komentar.
BoxWithConstraints(
modifier = modifier
.fillMaxWidth()
.background(color = MaterialTheme.colors.surface),
contentAlignment = Alignment.Center,
) {
val density = LocalDensity.current
val maxWidth = with(density) { constraints.maxWidth.toDp() }
val maxHeight = commentItemHeight - 16.dp
CommentListItem(
avatarId = comment.avatarId,
name = comment.name,
text = comment.text,
date = comment.date,
onClick = { onClick(comment) },
)
ActionPanel(
modifier = Modifier
.align(Alignment.CenterEnd)
.padding(horizontal = 16.dp),
maxWidth = maxWidth,
maxHeight = maxHeight,
isVisible = isActionsVisible,
onActionClick = onActionClick
)
}
Saat targetStateberubah, transisi akan menjalankan semua animasi anaknya menuju nilai target yang ditentukan untuk targetState. Jika Anda belum pernah bekerja dengan animasi sebelumnya, perhatikan bahwa labelalat Android Studio diperlukan untuk membedakan antara animasi.
Mari pertimbangkan animasi yang meluas. Kami menggunakan transitionSpecuntuk mengatur animasi dan menentukan animasi untuk setiap pasangan initialStatedan targetState. Parameter keyframesmenentukan fase animasi berdasarkan nilai snapshot yang ditetapkan pada titik waktu yang berbeda selama animasi. Pada waktu tertentu, nilai animasi akan diinterpolasi antara dua nilai keyframe. Dalam hal ini, animasi ketinggian dimulai dengan kecepatan tertentu untuk CORNER_DURATION, lalu dilanjutkan dengan kecepatan berbeda untuk EXPAND_DURATION. Untuk informasi mendalam, Anda dapat berkonsultasi dengan dokumentasi resmi
val stateTransition = updateTransition(targetState = isVisible, label = "Visibility")
val targetWidth = stateTransition.animateDp(
transitionSpec = {
keyframes {
durationMillis = CORNER_DURATION + EXPAND_DURATION
if (targetState) {
maxHeight at CORNER_DURATION
maxWidth at CORNER_DURATION + EXPAND_DURATION
} else {
maxHeight at EXPAND_DURATION
MIN_RADIUS.dp at EXPAND_DURATION + CORNER_DURATION
}
}
},
label = "Width"
) { value -> if (value) maxWidth else MIN_RADIUS.dp }
val targetHeight by stateTransition.animateDp(
transitionSpec = {
keyframes {
durationMillis = CORNER_DURATION + EXPAND_DURATION
if (targetState) {
maxHeight at CORNER_DURATION
} else {
maxHeight at EXPAND_DURATION
MIN_RADIUS.dp at EXPAND_DURATION + CORNER_DURATION
}
}
},
label = "Height"
) { value -> if (value) maxHeight else MIN_RADIUS.dp }
val contentAlphaProvider = remember {
{ (targetWidth.value - MIN_RADIUS.dp) / (maxWidth - MIN_RADIUS.dp) }
}

![Apa itu Linked List? [Bagian 1]](https://post.nghiatu.com/assets/images/m/max/724/1*Xokk6XOjWyIGCBujkJsCzQ.jpeg)



































