Tasarımda hareketli nesneler kullanıcının dikkatini çeken ve kullanıcı deneyimini arttıran görsel çalışmalardır.
Bu makale Jetpack Compose tasarım yapısında InfiniteTransition ve UpdateTransition Api’lerini kullanarak farklı animasyonları oluşturmayı örnekleyecektir.
Compose ile Animasyon Oluşturma Part 1 makalemizde de Animatable ve Animate*AsState Api’lerini örnekleyerek açıklamıştık.
1- UpdateTransition
updateTransition, birden fazla animasyon değerini yönetebilen ve bunları bir durum değişikliğine göre çalıştırabilen bir geçiş nesnesi oluşturur.
Örneğimizi inceleyelim. Başta resim boyutu 100 dp ve border siyah renktedir. Butona tıkladığında resim boyutu büyüyor ve border rengi mor olmaktadır. Yani iki animasyon değişikliği aynı anda olmaktadır. Kodlar;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
import androidx.compose.foundation.* import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.compose.animation.animateColor import androidx.compose.animation.core.animateDp import androidx.compose.animation.core.updateTransition import androidx.compose.foundation.layout.* import androidx.compose.foundation.shape.CircleShape import androidx.compose.material3.* import androidx.compose.runtime.* import androidx.compose.ui.* import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.painterResource import androidx.compose.ui.unit.dp import com.smality.animationswithcompose.ui.theme.AnimationsWithComposeTheme class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { AnimationsWithComposeTheme { updateTransitionExam() } } } } private enum class ImageState { Small, Large } @Composable fun updateTransitionExam() { var imageState by remember { mutableStateOf(ImageState.Small) } val transition = updateTransition(targetState = imageState, label = "BoxState Transition") //Renk değişimini sağlayan animasyon val borderColor by transition.animateColor(label = "BoxState Color Transition") { when (it) { ImageState.Small -> Color.Black ImageState.Large -> Color.Magenta } } //Boyut değişimini sağlayan animasyon val size by transition.animateDp(label = "BoxState Size Transition") { when (it) { ImageState.Small -> 100.dp ImageState.Large -> 140.dp } } Column( modifier = Modifier.fillMaxSize(), verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.CenterHorizontally ) { //Kedi resmini çember şekli içinde oluşturma Image( modifier = Modifier .size(size = size) .clip(shape = CircleShape) .border(color = borderColor, shape = CircleShape, width = 3.dp), painter = painterResource(id = R.drawable.cat), contentDescription = "Dog" ) Button( modifier = Modifier.padding(top = 8.dp), onClick = { imageState = if (imageState == ImageState.Small) ImageState.Large else ImageState.Small } ) { Text(text = "Toggle State") } } } |
2- InfiniteTransition
Jetpack Compose’da bir animasyonu sonsuza kadar çalıştırmanın en kolay yolu InfiniteTransition kullanmaktır. InfiniteTransition alt animasyonları olan animateColor, animateFloat veya animateValue birini kullanabilirsiniz. Kullanıcın istediği bir anda da animasyonu durdurabilirsiniz.
RepeatMode:
Animasyon, her yinelemeden sonra yeniden başlatılabilir (ör. RepeatMode.Restart) veya her yinelemeden sonra tersine çevrilebilir (ör. RepeatMode.Reverse).
animateFloat fonsiyonunda initialValue ve targetValue değerlerinde verilen boyutlara göre kalp ikonunu sürekli büyüyüp küçülmektedir. Stop butonu ile animasyonu durdurabiliyoruz. Kodlar;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
import androidx.compose.animation.core.RepeatMode import androidx.compose.ui.draw.scale import androidx.compose.material.icons.Icons import androidx.compose.material.icons.outlined.Favorite import androidx.compose.animation.core.* import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.compose.foundation.layout.* import androidx.compose.material3.* import androidx.compose.runtime.* import androidx.compose.ui.* import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp import com.smality.animationswithcompose.ui.theme.AnimationsWithComposeTheme class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { AnimationsWithComposeTheme { InfiniteTransitionExam() } } } } @Composable fun InfiniteTransitionExam() { //Animasyonu durdurabilmek için bir hatırlatıcı var animationRunning by remember { mutableStateOf(true) } if (animationRunning) { val transition = rememberInfiniteTransition() val scale by transition.animateFloat( initialValue = 1f, targetValue = 1.5f, animationSpec = infiniteRepeatable( //1 saniyede bir tekrar edecek animation = tween(durationMillis = 1000), repeatMode = RepeatMode.Reverse ) ) Column(Modifier.fillMaxWidth().absolutePadding(10.dp, 20.dp, 10.dp, 0.dp), horizontalAlignment = Alignment.CenterHorizontally) { Box( Modifier .fillMaxWidth() .fillMaxHeight(0.2f) ) // Kalp iconunu oluşturma Icon( imageVector = Icons.Outlined.Favorite, contentDescription = "Favorite", tint = Color.Red, modifier = Modifier .scale(scale = scale) .size(size = 85.dp) ) } } Column(Modifier.fillMaxWidth().absolutePadding(10.dp, 300.dp, 10.dp, 0.dp), horizontalAlignment = Alignment.CenterHorizontally) { // stop button Button(onClick = { animationRunning = false }) { Text(text = "STOP") } } } |