Jetpack Compose: āđāļ­āļ™āļīāđ€āļĄāļŠāļąāļ™āļ‚āļąāđ‰āļ™āļŠāļđāļ‡āļ—āļĩāļĨāļ°āļ‚āļąāđ‰āļ™āļ•āļ­āļ™

āļ„āļđāđˆāļĄāļ·āļ­āļ‰āļšāļąāļšāļŠāļĄāļšāļđāļĢāļ“āđŒāđ€āļāļĩāđˆāļĒāļ§āļāļąāļšāđāļ­āļ™āļīāđ€āļĄāļŠāļąāļ™āļ‚āļąāđ‰āļ™āļŠāļđāļ‡āđƒāļ™ Compose: āļ—āļĢāļēāļ™āļ‹āļīāļŠāļąāļ™ AnimatedVisibility, Animatable, āļ—āđˆāļēāļ—āļēāļ‡ āđāļĨāļ°āļ›āļĢāļ°āļŠāļīāļ—āļ˜āļīāļ āļēāļžāļŠāļģāļŦāļĢāļąāļšāļ­āļīāļ™āđ€āļ—āļ­āļĢāđŒāđ€āļŸāļ‹ Android āļ—āļĩāđˆāļĨāļ·āđˆāļ™āđ„āļŦāļĨ

āđāļ­āļ™āļīāđ€āļĄāļŠāļąāļ™āļ‚āļąāđ‰āļ™āļŠāļđāļ‡āļ‚āļ­āļ‡ Jetpack Compose āļŠāļģāļŦāļĢāļąāļšāļ™āļąāļāļžāļąāļ’āļ™āļē Android

āđāļ­āļ™āļīāđ€āļĄāļŠāļąāļ™āđ€āļ›āļĨāļĩāđˆāļĒāļ™āđāļ­āļ›āļžāļĨāļīāđ€āļ„āļŠāļąāļ™āđ€āļŠāļīāļ‡āļŸāļąāļ‡āļāđŒāļŠāļąāļ™āđƒāļŦāđ‰āļāļĨāļēāļĒāđ€āļ›āđ‡āļ™āļ›āļĢāļ°āļŠāļšāļāļēāļĢāļ“āđŒāļœāļđāđ‰āđƒāļŠāđ‰āļ—āļĩāđˆāļ™āđˆāļēāļˆāļ”āļˆāļģ Jetpack Compose āļĄāļĩ API āđāļ­āļ™āļīāđ€āļĄāļŠāļąāļ™āđāļšāļšāļ›āļĢāļ°āļāļēāļĻāļ—āļĩāđˆāļ—āļĢāļ‡āļžāļĨāļąāļ‡āļ‹āļķāđˆāļ‡āļŠāđˆāļ§āļĒāđƒāļŦāđ‰āļāļēāļĢāļŠāļĢāđ‰āļēāļ‡āļ­āļīāļ™āđ€āļ—āļ­āļĢāđŒāđ€āļŸāļ‹āļ—āļĩāđˆāļĨāļ·āđˆāļ™āđ„āļŦāļĨāļ‡āđˆāļēāļĒāļ‚āļķāđ‰āļ™āļ­āļĒāđˆāļēāļ‡āļĄāļēāļ āļ„āļđāđˆāļĄāļ·āļ­āļ™āļĩāđ‰āļŠāļģāļĢāļ§āļˆāđ€āļ—āļ„āļ™āļīāļ„āļ‚āļąāđ‰āļ™āļŠāļđāļ‡āđƒāļ™āļāļēāļĢāļŠāļĢāđ‰āļēāļ‡āđāļ­āļ™āļīāđ€āļĄāļŠāļąāļ™āļ—āļĩāđˆāļĄāļĩāļ›āļĢāļ°āļŠāļīāļ—āļ˜āļīāļ āļēāļžāđāļĨāļ°āļšāļģāļĢāļļāļ‡āļĢāļąāļāļĐāļēāļ‡āđˆāļēāļĒ

āļ‚āđ‰āļ­āļāļģāļŦāļ™āļ”āđ€āļšāļ·āđ‰āļ­āļ‡āļ•āđ‰āļ™

āļšāļ—āđāļ™āļ°āļ™āļģāļ™āļĩāđ‰āļŠāļąāļ™āļ™āļīāļĐāļāļēāļ™āļ§āđˆāļēāļœāļđāđ‰āļ­āđˆāļēāļ™āļ„āļļāđ‰āļ™āđ€āļ„āļĒāļāļąāļšāļžāļ·āđ‰āļ™āļāļēāļ™āļ‚āļ­āļ‡ Compose (recomposition, state, modifier) āļŠāļģāļŦāļĢāļąāļšāļžāļ·āđ‰āļ™āļāļēāļ™āļ„āļ§āļĢāļ­āđˆāļēāļ™āļ„āļđāđˆāļĄāļ·āļ­āļ„āļģāļ–āļēāļĄāļŠāļąāļĄāļ āļēāļĐāļ“āđŒ Jetpack Compose āļāđˆāļ­āļ™

āļžāļ·āđ‰āļ™āļāļēāļ™āļ‚āļ­āļ‡ API āđāļ­āļ™āļīāđ€āļĄāļŠāļąāļ™āđƒāļ™ Compose

Compose āļĄāļĩ API āļŦāļĨāļēāļĒāļĢāļ°āļ”āļąāļšāļŠāļģāļŦāļĢāļąāļšāđāļ­āļ™āļīāđ€āļĄāļŠāļąāļ™ āļāļēāļĢāđ€āļĨāļ·āļ­āļāļ‚āļķāđ‰āļ™āļ­āļĒāļđāđˆāļāļąāļšāļĢāļ°āļ”āļąāļšāļāļēāļĢāļ„āļ§āļšāļ„āļļāļĄāļ—āļĩāđˆāļ•āđ‰āļ­āļ‡āļāļēāļĢāđāļĨāļ°āļ„āļ§āļēāļĄāļ‹āļąāļšāļ‹āđ‰āļ­āļ™āļ‚āļ­āļ‡āđāļ­āļ™āļīāđ€āļĄāļŠāļąāļ™

API āđāļšāđˆāļ‡āļ­āļ­āļāđ€āļ›āđ‡āļ™āļŠāļēāļĄāļ›āļĢāļ°āđ€āļ āļ—āļŦāļĨāļąāļ āđ„āļ”āđ‰āđāļāđˆ āđāļ­āļ™āļīāđ€āļĄāļŠāļąāļ™āļĢāļ°āļ”āļąāļšāļŠāļđāļ‡ (AnimatedVisibility, AnimatedContent) āđāļ­āļ™āļīāđ€āļĄāļŠāļąāļ™āļ—āļĩāđˆāļ­āļīāļ‡āļ•āļēāļĄāļŠāļ–āļēāļ™āļ° (animate*AsState) āđāļĨāļ°āđāļ­āļ™āļīāđ€āļĄāļŠāļąāļ™āļĢāļ°āļ”āļąāļšāļ•āđˆāļģ (Animatable, Transition)

AnimationLevels.ktkotlin
// Overview of the three animation API levels
@Composable
fun AnimationApiOverview() {
    // High level: simple predefined animations
    AnimatedVisibility(visible = isVisible) {
        Text("Animated content")
    }

    // Intermediate level: state-driven animation
    val alpha by animateFloatAsState(
        targetValue = if (isSelected) 1f else 0.5f,
        label = "alpha"
    )

    // Low level: full control over animation
    val animatable = remember { Animatable(0f) }
    LaunchedEffect(targetValue) {
        animatable.animateTo(targetValue)
    }
}

āļāļēāļĢāđ€āļĨāļ·āļ­āļāļĢāļ°āļ”āļąāļš API āļ—āļĩāđˆāđ€āļŦāļĄāļēāļ°āļŠāļĄāđ€āļ›āđ‡āļ™āļŠāļīāđˆāļ‡āļŠāļģāļ„āļąāļāđ€āļžāļ·āđˆāļ­āļĢāļąāļāļĐāļēāđ‚āļ„āđ‰āļ”āđƒāļŦāđ‰āļ­āđˆāļēāļ™āļ‡āđˆāļēāļĒāļ‚āļ“āļ°āļ—āļĩāđˆāļĒāļąāļ‡āļ„āļ‡āļ„āļ§āļēāļĄāļĒāļ·āļ”āļŦāļĒāļļāđˆāļ™āļ—āļĩāđˆāļˆāļģāđ€āļ›āđ‡āļ™

AnimatedVisibility: āđāļ­āļ™āļīāđ€āļĄāļŠāļąāļ™āļāļēāļĢāđ€āļ‚āđ‰āļēāđāļĨāļ°āļ­āļ­āļāļ—āļĩāđˆāļŦāļĢāļđāļŦāļĢāļē

AnimatedVisibility āđ€āļ›āđ‡āļ™āļˆāļļāļ”āđ€āļĢāļīāđˆāļĄāļ•āđ‰āļ™āļ—āļĩāđˆāđ€āļŦāļĄāļēāļ°āļŠāļģāļŦāļĢāļąāļšāļāļēāļĢāđāļ­āļ™āļīāđ€āļĄāļ•āļāļēāļĢāļ›āļĢāļēāļāļāđāļĨāļ°āļŦāļēāļĒāđ„āļ›āļ‚āļ­āļ‡āļ­āļīāļĨāļīāđ€āļĄāļ™āļ•āđŒ API āļ™āļĩāđ‰āļˆāļąāļ”āļāļēāļĢāļāļēāļĢāļ„āļ­āļĄāđ‚āļžāļŠāđāļĨāļ°āļ”āļĩāļ„āļ­āļĄāđ‚āļžāļŠāđ€āļ™āļ·āđ‰āļ­āļŦāļēāđ‚āļ”āļĒāļ­āļąāļ•āđ‚āļ™āļĄāļąāļ•āļī

āļžāļēāļĢāļēāļĄāļīāđ€āļ•āļ­āļĢāđŒ enter āđāļĨāļ° exit āļĢāļąāļšāļāļēāļĢāļĢāļ§āļĄāļāļąāļ™āļ‚āļ­āļ‡āļ—āļĢāļēāļ™āļ‹āļīāļŠāļąāļ™āļ—āļĩāđˆāļāļģāļŦāļ™āļ”āļžāļĪāļ•āļīāļāļĢāļĢāļĄāļ‚āļ­āļ‡āđāļ­āļ™āļīāđ€āļĄāļŠāļąāļ™ āļ—āļĢāļēāļ™āļ‹āļīāļŠāļąāļ™āđ€āļŦāļĨāđˆāļēāļ™āļĩāđ‰āļŠāļēāļĄāļēāļĢāļ–āļĢāļ§āļĄāļāļąāļ™āļ”āđ‰āļ§āļĒāļ•āļąāļ§āļ”āļģāđ€āļ™āļīāļ™āļāļēāļĢ +

AnimatedVisibilityExample.ktkotlin
@Composable
fun ExpandableCard(
    title: String,
    content: String,
    modifier: Modifier = Modifier
) {
    var isExpanded by remember { mutableStateOf(false) }

    Card(
        modifier = modifier.clickable { isExpanded = !isExpanded }
    ) {
        Column(modifier = Modifier.padding(16.dp)) {
            Row(
                modifier = Modifier.fillMaxWidth(),
                horizontalArrangement = Arrangement.SpaceBetween
            ) {
                Text(text = title, style = MaterialTheme.typography.titleMedium)
                Icon(
                    imageVector = if (isExpanded) Icons.Default.ExpandLess
                                  else Icons.Default.ExpandMore,
                    contentDescription = null
                )
            }

            // Expansion animation with fade + slide
            AnimatedVisibility(
                visible = isExpanded,
                enter = fadeIn(animationSpec = tween(300)) +
                        expandVertically(animationSpec = tween(300)),
                exit = fadeOut(animationSpec = tween(200)) +
                       shrinkVertically(animationSpec = tween(200))
            ) {
                Text(
                    text = content,
                    modifier = Modifier.padding(top = 12.dp),
                    style = MaterialTheme.typography.bodyMedium
                )
            }
        }
    }
}

āđ€āļ™āļ·āđ‰āļ­āļŦāļēāļ āļēāļĒāđƒāļ™ AnimatedVisibility āļˆāļ°āļ–āļđāļāļ„āļ­āļĄāđ‚āļžāļŠāđ€āļ‰āļžāļēāļ°āđ€āļĄāļ·āđˆāļ­ visible = true āļ‹āļķāđˆāļ‡āļŠāđˆāļ§āļĒāļ›āļĢāļąāļšāļ›āļĢāļ°āļŠāļīāļ—āļ˜āļīāļ āļēāļžāļŠāļģāļŦāļĢāļąāļšāļĢāļēāļĒāļāļēāļĢāļ—āļĩāđˆāļĄāļĩāļ­āļīāļĨāļīāđ€āļĄāļ™āļ•āđŒāļ—āļĩāđˆāļ‚āļĒāļēāļĒāđ„āļ”āđ‰āļˆāļģāļ™āļ§āļ™āļĄāļēāļ

āļāļēāļĢāļĢāļ§āļĄāļ—āļĢāļēāļ™āļ‹āļīāļŠāļąāļ™

āļ—āļĢāļēāļ™āļ‹āļīāļŠāļąāļ™āļ—āļĩāđˆāđƒāļŠāđ‰āđ„āļ”āđ‰ āđ„āļ”āđ‰āđāļāđˆ fadeIn/fadeOut, slideIn/slideOut, expandIn/shrinkOut, scaleIn/scaleOut āļŠāļēāļĄāļēāļĢāļ–āļĢāļ§āļĄāļāļąāļ™āđ„āļ”āđ‰āļ­āļĒāđˆāļēāļ‡āļ­āļīāļŠāļĢāļ°āđ€āļžāļ·āđˆāļ­āļŠāļĢāđ‰āļēāļ‡āđ€āļ­āļŸāđ€āļŸāļāļ•āđŒāļ—āļĩāđˆāļāļģāļŦāļ™āļ”āđ€āļ­āļ‡

animate*AsState: āđāļ­āļ™āļīāđ€āļĄāļŠāļąāļ™āļ—āļĩāđˆāļ‚āļąāļšāđ€āļ„āļĨāļ·āđˆāļ­āļ™āļ”āđ‰āļ§āļĒāļŠāļ–āļēāļ™āļ°

āļāļĨāļļāđˆāļĄāļŸāļąāļ‡āļāđŒāļŠāļąāļ™ animate*AsState āđāļ­āļ™āļīāđ€āļĄāļ•āļāļēāļĢāđ€āļ›āļĨāļĩāđˆāļĒāļ™āđāļ›āļĨāļ‡āļ‚āļ­āļ‡āļ„āđˆāļēāļžāļ·āđ‰āļ™āļāļēāļ™āđ‚āļ”āļĒāļ­āļąāļ•āđ‚āļ™āļĄāļąāļ•āļī āļ™āļĩāđˆāļ„āļ·āļ­āđāļ™āļ§āļ—āļēāļ‡āļ—āļĩāđˆāđ€āļ›āđ‡āļ™āđ€āļ­āļāļĨāļąāļāļĐāļ“āđŒāļ—āļĩāđˆāļŠāļļāļ”āļŠāļģāļŦāļĢāļąāļšāđāļ­āļ™āļīāđ€āļĄāļŠāļąāļ™āļ˜āļĢāļĢāļĄāļ”āļēāđƒāļ™ Compose

āļ‚āđ‰āļ­āļĄāļđāļĨāđāļ•āđˆāļĨāļ°āļ›āļĢāļ°āđ€āļ āļ—āļĄāļĩāļŸāļąāļ‡āļāđŒāļŠāļąāļ™āđ€āļ‰āļžāļēāļ°āļ‚āļ­āļ‡āļ•āļ™: animateColorAsState, animateFloatAsState, animateDpAsState, animateIntAsState āđ€āļ›āđ‡āļ™āļ•āđ‰āļ™

AnimateAsStateExample.ktkotlin
@Composable
fun InteractiveButton(
    isSelected: Boolean,
    onClick: () -> Unit,
    modifier: Modifier = Modifier
) {
    // Animated background color
    val backgroundColor by animateColorAsState(
        targetValue = if (isSelected) MaterialTheme.colorScheme.primary
                      else MaterialTheme.colorScheme.surfaceVariant,
        animationSpec = tween(durationMillis = 250),
        label = "backgroundColor"
    )

    // Animated elevation
    val elevation by animateDpAsState(
        targetValue = if (isSelected) 8.dp else 2.dp,
        animationSpec = spring(
            dampingRatio = Spring.DampingRatioMediumBouncy,
            stiffness = Spring.StiffnessLow
        ),
        label = "elevation"
    )

    // Animated text size
    val textSize by animateFloatAsState(
        targetValue = if (isSelected) 18f else 14f,
        label = "textSize"
    )

    Surface(
        modifier = modifier.clickable(onClick = onClick),
        color = backgroundColor,
        shadowElevation = elevation,
        shape = RoundedCornerShape(12.dp)
    ) {
        Text(
            text = if (isSelected) "Selected" else "Select",
            modifier = Modifier.padding(horizontal = 24.dp, vertical = 12.dp),
            fontSize = textSize.sp
        )
    }
}

āļžāļēāļĢāļēāļĄāļīāđ€āļ•āļ­āļĢāđŒ animationSpec āļ„āļ§āļšāļ„āļļāļĄāļžāļĪāļ•āļīāļāļĢāļĢāļĄāđ€āļŠāļīāļ‡āđ€āļ§āļĨāļēāļ‚āļ­āļ‡āđāļ­āļ™āļīāđ€āļĄāļŠāļąāļ™ Spec āļ—āļĩāđˆāđƒāļŠāđ‰āļšāđˆāļ­āļĒāļ—āļĩāđˆāļŠāļļāļ”āļŠāļ­āļ‡āļĢāļēāļĒāļāļēāļĢāļ„āļ·āļ­ tween (āļĢāļ°āļĒāļ°āđ€āļ§āļĨāļēāļ„āļ‡āļ—āļĩāđˆāļžāļĢāđ‰āļ­āļĄ easing) āđāļĨāļ° spring (āļŸāļīāļŠāļīāļāļŠāđŒāļ—āļĩāđˆāļŠāļĄāļˆāļĢāļīāļ‡āļžāļĢāđ‰āļ­āļĄāļāļēāļĢāđ€āļ”āđ‰āļ‡)

Transition: āļāļēāļĢāļ›āļĢāļ°āļŠāļēāļ™āļ‡āļēāļ™āļŦāļĨāļēāļĒāđāļ­āļ™āļīāđ€āļĄāļŠāļąāļ™

āđ€āļĄāļ·āđˆāļ­āļ•āđ‰āļ­āļ‡āđāļ­āļ™āļīāđ€āļĄāļ•āļ„āļļāļ“āļŠāļĄāļšāļąāļ•āļīāļŦāļĨāļēāļĒāļ­āļĒāđˆāļēāļ‡āđƒāļŦāđ‰āļ›āļĢāļ°āļŠāļēāļ™āļāļąāļ™ updateTransition āđƒāļŦāđ‰āļāļēāļĢāļ„āļ§āļšāļ„āļļāļĄāđāļšāļšāļĢāļ§āļĄāļĻāļđāļ™āļĒāđŒ API āļ™āļĩāđ‰āļĢāļąāļšāļ›āļĢāļ°āļāļąāļ™āļ§āđˆāļēāđāļ­āļ™āļīāđ€āļĄāļŠāļąāļ™āļ—āļąāđ‰āļ‡āļŦāļĄāļ”āļˆāļ°āļ„āļ‡āļāļēāļĢāļ›āļĢāļ°āļŠāļēāļ™āđ€āļ§āļĨāļēāđ„āļ§āđ‰

āļĢāļđāļ›āđāļšāļšāļ™āļĩāđ‰āļ›āļĢāļ°āļāļ­āļšāļ”āđ‰āļ§āļĒāļāļēāļĢāļāļģāļŦāļ™āļ”āļŠāļ–āļēāļ™āļ°āđāļšāļš enum āļˆāļēāļāļ™āļąāđ‰āļ™āļŠāļĢāđ‰āļēāļ‡āđāļ­āļ™āļīāđ€āļĄāļŠāļąāļ™āļŠāļģāļŦāļĢāļąāļšāļ„āļļāļ“āļŠāļĄāļšāļąāļ•āļīāđāļ•āđˆāļĨāļ°āļ­āļĒāđˆāļēāļ‡āļ—āļĩāđˆāļ‚āļķāđ‰āļ™āļ­āļĒāļđāđˆāļāļąāļšāļŠāļ–āļēāļ™āļ°āļ™āļąāđ‰āļ™

TransitionExample.ktkotlin
// Card state: defines visual behavior
enum class CardState { Collapsed, Expanded, Selected }

@Composable
fun AnimatedStateCard(
    cardState: CardState,
    modifier: Modifier = Modifier
) {
    // Central transition coordinating all animations
    val transition = updateTransition(
        targetState = cardState,
        label = "cardTransition"
    )

    // Card height based on state
    val cardHeight by transition.animateDp(
        transitionSpec = { spring(stiffness = Spring.StiffnessLow) },
        label = "height"
    ) { state ->
        when (state) {
            CardState.Collapsed -> 80.dp
            CardState.Expanded -> 200.dp
            CardState.Selected -> 160.dp
        }
    }

    // Border color based on state
    val borderColor by transition.animateColor(
        transitionSpec = { tween(300) },
        label = "borderColor"
    ) { state ->
        when (state) {
            CardState.Collapsed -> Color.Transparent
            CardState.Expanded -> MaterialTheme.colorScheme.outline
            CardState.Selected -> MaterialTheme.colorScheme.primary
        }
    }

    // Corner radius based on state
    val cornerRadius by transition.animateDp(
        label = "cornerRadius"
    ) { state ->
        when (state) {
            CardState.Collapsed -> 8.dp
            CardState.Expanded -> 16.dp
            CardState.Selected -> 24.dp
        }
    }

    Card(
        modifier = modifier
            .height(cardHeight)
            .border(2.dp, borderColor, RoundedCornerShape(cornerRadius)),
        shape = RoundedCornerShape(cornerRadius)
    ) {
        // Card content
    }
}

āļžāļĢāđ‰āļ­āļĄāļ—āļĩāđˆāļˆāļ°āļžāļīāļŠāļīāļ•āļāļēāļĢāļŠāļąāļĄāļ āļēāļĐāļ“āđŒ Android āđāļĨāđ‰āļ§āļŦāļĢāļ·āļ­āļĒāļąāļ‡āļ„āļĢāļąāļš?

āļāļķāļāļāļ™āļ”āđ‰āļ§āļĒāļ•āļąāļ§āļˆāļģāļĨāļ­āļ‡āđāļšāļšāđ‚āļ•āđ‰āļ•āļ­āļš, flashcards āđāļĨāļ°āđāļšāļšāļ—āļ”āļŠāļ­āļšāđ€āļ—āļ„āļ™āļīāļ„āļ„āļĢāļąāļš

Animatable: āļāļēāļĢāļ„āļ§āļšāļ„āļļāļĄāđāļ­āļ™āļīāđ€āļĄāļŠāļąāļ™āđ€āļ•āđ‡āļĄāļĢāļđāļ›āđāļšāļš

Animatable āđ€āļ›āđ‡āļ™ API āļĢāļ°āļ”āļąāļšāļ•āđˆāļģāļ—āļĩāđˆāđƒāļŦāđ‰āļāļēāļĢāļ„āļ§āļšāļ„āļļāļĄāđ€āļŠāļīāļ‡āđ‚āļ›āļĢāđāļāļĢāļĄāļ­āļĒāđˆāļēāļ‡āļŠāļĄāļšāļđāļĢāļ“āđŒ āđāļ™āļ§āļ—āļēāļ‡āļ™āļĩāđ‰āļˆāļģāđ€āļ›āđ‡āļ™āļŠāļģāļŦāļĢāļąāļšāđāļ­āļ™āļīāđ€āļĄāļŠāļąāļ™āļ—āļĩāđˆāļŠāļēāļĄāļēāļĢāļ–āļ–āļđāļāļ‚āļąāļ”āļˆāļąāļ‡āļŦāļ§āļ°āđ„āļ”āđ‰ āļ—āđˆāļēāļ—āļēāļ‡ āļŦāļĢāļ·āļ­āļŠāļ–āļēāļ™āļāļēāļĢāļ“āđŒāļ—āļĩāđˆāļ‹āļąāļšāļ‹āđ‰āļ­āļ™

āļ•āđˆāļēāļ‡āļˆāļēāļ animate*AsState, Animatable āļŠāđˆāļ§āļĒāđƒāļŦāđ‰āļŠāļēāļĄāļēāļĢāļ–āļŦāļĒāļļāļ” āļĒāđ‰āļ­āļ™āļāļĨāļąāļš āļŦāļĢāļ·āļ­āļ›āļĢāļąāļšāđ€āļ›āļĨāļĩāđˆāļĒāļ™āđāļ­āļ™āļīāđ€āļĄāļŠāļąāļ™āļ—āļĩāđˆāļāļģāļĨāļąāļ‡āļ”āļģāđ€āļ™āļīāļ™āļāļēāļĢāđ„āļ”āđ‰āđ‚āļ”āļĒāđ„āļĄāđˆāļ•āđ‰āļ­āļ‡āļĢāļ­āđƒāļŦāđ‰āđ€āļŠāļĢāđ‡āļˆāļŠāļīāđ‰āļ™

AnimatableExample.ktkotlin
@Composable
fun SwipeableCard(
    onDismiss: () -> Unit,
    modifier: Modifier = Modifier,
    content: @Composable () -> Unit
) {
    // Horizontal offset controlled by Animatable
    val offsetX = remember { Animatable(0f) }
    val scope = rememberCoroutineScope()

    // Swipe threshold to trigger dismissal
    val dismissThreshold = 300f

    Box(
        modifier = modifier
            .offset { IntOffset(offsetX.value.roundToInt(), 0) }
            .pointerInput(Unit) {
                detectHorizontalDragGestures(
                    onDragEnd = {
                        scope.launch {
                            if (abs(offsetX.value) > dismissThreshold) {
                                // Animate out then callback
                                val target = if (offsetX.value > 0) 1000f else -1000f
                                offsetX.animateTo(
                                    targetValue = target,
                                    animationSpec = tween(200)
                                )
                                onDismiss()
                            } else {
                                // Return to initial position with spring
                                offsetX.animateTo(
                                    targetValue = 0f,
                                    animationSpec = spring(
                                        dampingRatio = Spring.DampingRatioMediumBouncy
                                    )
                                )
                            }
                        }
                    },
                    onHorizontalDrag = { _, dragAmount ->
                        scope.launch {
                            // snapTo for instant finger tracking
                            offsetX.snapTo(offsetX.value + dragAmount)
                        }
                    }
                )
            }
    ) {
        content()
    }
}

āđ€āļĄāļ˜āļ­āļ”āļŠāļģāļ„āļąāļāļ‚āļ­āļ‡ Animatable āļ„āļ·āļ­ animateTo() (āđāļ­āļ™āļīāđ€āļĄāļ•āđ„āļ›āļĒāļąāļ‡āđ€āļ›āđ‰āļēāļŦāļĄāļēāļĒ) snapTo() (āđ€āļ›āļĨāļĩāđˆāļĒāļ™āļ—āļąāļ™āļ—āļĩ) āđāļĨāļ° stop() (āļ‚āļąāļ”āļˆāļąāļ‡āļŦāļ§āļ°)

AnimatedContent: āļ—āļĢāļēāļ™āļ‹āļīāļŠāļąāļ™āļ‚āļ­āļ‡āđ€āļ™āļ·āđ‰āļ­āļŦāļē

AnimatedContent āđāļ­āļ™āļīāđ€āļĄāļ•āļ—āļĢāļēāļ™āļ‹āļīāļŠāļąāļ™āļĢāļ°āļŦāļ§āđˆāļēāļ‡āđ€āļ™āļ·āđ‰āļ­āļŦāļēāļ—āļĩāđˆāđāļ•āļāļ•āđˆāļēāļ‡āļāļąāļ™ API āļ™āļĩāđ‰āđ€āļŦāļĄāļēāļ°āļŠāļģāļŦāļĢāļąāļšāļāļēāļĢāđ€āļ›āļĨāļĩāđˆāļĒāļ™āđāļ›āļĨāļ‡āļŠāļ–āļēāļ™āļ°āļ—āļĩāđˆāļ›āļĢāļąāļšāđ€āļ›āļĨāļĩāđˆāļĒāļ™ UI āļ—āļĩāđˆāđāļŠāļ”āļ‡āđ‚āļ”āļĒāļŠāļīāđ‰āļ™āđ€āļŠāļīāļ‡

āļ„āļĩāļĒāđŒ targetState āļāļģāļŦāļ™āļ”āļ§āđˆāļēāļ—āļĢāļēāļ™āļ‹āļīāļŠāļąāļ™āļ„āļ§āļĢāđ€āļāļīāļ”āļ‚āļķāđ‰āļ™āđ€āļĄāļ·āđˆāļ­āđƒāļ” transitionSpec āļāļģāļŦāļ™āļ”āļ§āđˆāļēāđ€āļ™āļ·āđ‰āļ­āļŦāļēāļ—āļĩāđˆāļ­āļ­āļāđāļĨāļ°āđ€āļ™āļ·āđ‰āļ­āļŦāļēāļ—āļĩāđˆāđ€āļ‚āđ‰āļēāļˆāļ°āļĄāļĩāļ›āļāļīāļŠāļąāļĄāļžāļąāļ™āļ˜āđŒāļāļąāļ™āļ­āļĒāđˆāļēāļ‡āđ„āļĢ

AnimatedContentExample.ktkotlin
@Composable
fun CounterWithAnimation(
    count: Int,
    modifier: Modifier = Modifier
) {
    AnimatedContent(
        targetState = count,
        modifier = modifier,
        transitionSpec = {
            // Determine animation direction
            val direction = if (targetState > initialState) {
                // New number enters from top
                slideInVertically { height -> -height } + fadeIn() togetherWith
                slideOutVertically { height -> height } + fadeOut()
            } else {
                // New number enters from bottom
                slideInVertically { height -> height } + fadeIn() togetherWith
                slideOutVertically { height -> -height } + fadeOut()
            }
            direction.using(SizeTransform(clip = false))
        },
        label = "counter"
    ) { targetCount ->
        Text(
            text = "$targetCount",
            style = MaterialTheme.typography.displayLarge,
            fontWeight = FontWeight.Bold
        )
    }
}
āļ›āļĢāļ°āļŠāļīāļ—āļ˜āļīāļ āļēāļžāļ‚āļ­āļ‡ AnimatedContent

āđ€āļ™āļ·āđ‰āļ­āļŦāļēāļ āļēāļĒāđƒāļ™ AnimatedContent āļˆāļ°āļ–āļđāļ recompose āļ—āļļāļāļ„āļĢāļąāđ‰āļ‡āļ—āļĩāđˆ targetState āđ€āļ›āļĨāļĩāđˆāļĒāļ™ āļŠāļģāļŦāļĢāļąāļšāđ€āļ™āļ·āđ‰āļ­āļŦāļēāļ—āļĩāđˆāļ‹āļąāļšāļ‹āđ‰āļ­āļ™ āļ„āļ§āļĢāđ€āļāđ‡āļšāļ­āļīāļĨāļīāđ€āļĄāļ™āļ•āđŒāļ—āļĩāđˆāļĄāļĩāļ•āđ‰āļ™āļ—āļļāļ™āļŠāļđāļ‡āđ„āļ§āđ‰āđƒāļ™āđāļ„āļŠāļŦāļĢāļ·āļ­āđƒāļŠāđ‰āļāļĨāļĒāļļāļ—āļ˜āđŒāļ„āļĩāļĒāđŒāļ—āļĩāđˆāđ€āļŦāļĄāļēāļ°āļŠāļĄ

āđāļ­āļ™āļīāđ€āļĄāļŠāļąāļ™āđ„āļĄāđˆāļˆāļģāļāļąāļ”āļ”āđ‰āļ§āļĒ rememberInfiniteTransition

āļŠāļģāļŦāļĢāļąāļšāđāļ­āļ™āļīāđ€āļĄāļŠāļąāļ™āļ—āļĩāđˆāļ§āļ™āļ‹āđ‰āļģ (āļ•āļąāļ§āļšāđˆāļ‡āļŠāļĩāđ‰āļāļēāļĢāđ‚āļŦāļĨāļ” āđ€āļ­āļŸāđ€āļŸāļāļ•āđŒāļāļēāļĢāđ€āļ•āđ‰āļ™) rememberInfiniteTransition āļĄāļĩ API āđ€āļ‰āļžāļēāļ°āļ—āļĩāđˆāđ„āļĄāđˆāļ•āđ‰āļ­āļ‡āļˆāļąāļ”āļāļēāļĢāļĢāļ­āļšāļ”āđ‰āļ§āļĒāļ•āļ™āđ€āļ­āļ‡

InfiniteTransitionExample.ktkotlin
@Composable
fun PulsingDot(
    color: Color = MaterialTheme.colorScheme.primary,
    modifier: Modifier = Modifier
) {
    val infiniteTransition = rememberInfiniteTransition(label = "pulse")

    // Looping scale animation
    val scale by infiniteTransition.animateFloat(
        initialValue = 0.8f,
        targetValue = 1.2f,
        animationSpec = infiniteRepeatable(
            animation = tween(600, easing = FastOutSlowInEasing),
            repeatMode = RepeatMode.Reverse
        ),
        label = "scale"
    )

    // Synchronized opacity animation
    val alpha by infiniteTransition.animateFloat(
        initialValue = 0.5f,
        targetValue = 1f,
        animationSpec = infiniteRepeatable(
            animation = tween(600, easing = FastOutSlowInEasing),
            repeatMode = RepeatMode.Reverse
        ),
        label = "alpha"
    )

    Box(
        modifier = modifier
            .size(24.dp)
            .scale(scale)
            .alpha(alpha)
            .background(color = color, shape = CircleShape)
    )
}

āđāļ­āļ™āļīāđ€āļĄāļŠāļąāļ™āļĢāļēāļĒāļāļēāļĢāļ”āđ‰āļ§āļĒ LazyColumn

āđāļ­āļ™āļīāđ€āļĄāļŠāļąāļ™āļŠāļģāļŦāļĢāļąāļšāļĢāļēāļĒāļāļēāļĢāļ•āđ‰āļ­āļ‡āđƒāļŦāđ‰āļ„āļ§āļēāļĄāļŠāļģāļ„āļąāļāđ€āļ›āđ‡āļ™āļžāļīāđ€āļĻāļĐ Modifier animateItem() (āđ€āļ”āļīāļĄāļ„āļ·āļ­ animateItemPlacement) āđāļ­āļ™āļīāđ€āļĄāļ•āļāļēāļĢāļˆāļąāļ”āđ€āļĢāļĩāļĒāļ‡āđƒāļŦāļĄāđˆāđ‚āļ”āļĒāļ­āļąāļ•āđ‚āļ™āļĄāļąāļ•āļī

ListAnimationExample.ktkotlin
@Composable
fun AnimatedTaskList(
    tasks: List<Task>,
    onToggle: (Task) -> Unit,
    onDelete: (Task) -> Unit,
    modifier: Modifier = Modifier
) {
    LazyColumn(
        modifier = modifier,
        verticalArrangement = Arrangement.spacedBy(8.dp)
    ) {
        items(
            items = tasks,
            key = { it.id }  // Stable key required for animateItem
        ) { task ->
            var isVisible by remember { mutableStateOf(true) }

            // Exit animation before deletion
            AnimatedVisibility(
                visible = isVisible,
                exit = shrinkVertically() + fadeOut()
            ) {
                TaskItem(
                    task = task,
                    onToggle = { onToggle(task) },
                    onDelete = {
                        isVisible = false
                        // Delay to let animation complete
                    },
                    modifier = Modifier.animateItem(
                        fadeInSpec = tween(300),
                        fadeOutSpec = tween(300),
                        placementSpec = spring(
                            dampingRatio = Spring.DampingRatioMediumBouncy,
                            stiffness = Spring.StiffnessLow
                        )
                    )
                )
            }

            // Trigger deletion after animation
            LaunchedEffect(isVisible) {
                if (!isVisible) {
                    delay(300)
                    onDelete(task)
                }
            }
        }
    }
}
āļ„āļĩāļĒāđŒāļ—āļĩāđˆāđ€āļŠāļ–āļĩāļĒāļĢāļŠāļģāļŦāļĢāļąāļšāđāļ­āļ™āļīāđ€āļĄāļŠāļąāļ™āļĢāļēāļĒāļāļēāļĢ

āļŦāļēāļāđ„āļĄāđˆāļĄāļĩāļžāļēāļĢāļēāļĄāļīāđ€āļ•āļ­āļĢāđŒ key āļ—āļĩāđˆāđ€āļŠāļ–āļĩāļĒāļĢ animateItem āļˆāļ°āđ„āļĄāđˆāļŠāļēāļĄāļēāļĢāļ–āļ•āļīāļ”āļ•āļēāļĄāļ­āļīāļĨāļīāđ€āļĄāļ™āļ•āđŒāļĢāļ°āļŦāļ§āđˆāļēāļ‡āļāļēāļĢ recompose āđ„āļ”āđ‰ āļ„āļ§āļĢāđƒāļŠāđ‰ ID āļ—āļĩāđˆāđ„āļĄāđˆāļ‹āđ‰āļģāđāļ—āļ™āļ”āļąāļŠāļ™āļĩāļ‚āļ­āļ‡āļĢāļēāļĒāļāļēāļĢ

āđāļ­āļ™āļīāđ€āļĄāļŠāļąāļ™ Canvas

āļŠāļģāļŦāļĢāļąāļšāđ€āļ­āļŸāđ€āļŸāļāļ•āđŒāļ āļēāļžāļ—āļĩāđˆāļāļģāļŦāļ™āļ”āđ€āļ­āļ‡ āļāļēāļĢāļĢāļ§āļĄ Canvas āļāļąāļšāļ„āđˆāļēāļ—āļĩāđˆāđāļ­āļ™āļīāđ€āļĄāļ•āđƒāļŦāđ‰āļ„āļ§āļēāļĄāļĒāļ·āļ”āļŦāļĒāļļāđˆāļ™āļ—āļąāđ‰āļ‡āļŦāļĄāļ”

CanvasAnimationExample.ktkotlin
@Composable
fun AnimatedProgressRing(
    progress: Float,  // 0f to 1f
    modifier: Modifier = Modifier
) {
    // Progress animation with spring for natural feel
    val animatedProgress by animateFloatAsState(
        targetValue = progress,
        animationSpec = spring(
            dampingRatio = Spring.DampingRatioLowBouncy,
            stiffness = Spring.StiffnessVeryLow
        ),
        label = "progress"
    )

    // Continuous rotation animation
    val infiniteTransition = rememberInfiniteTransition(label = "rotation")
    val rotation by infiniteTransition.animateFloat(
        initialValue = 0f,
        targetValue = 360f,
        animationSpec = infiniteRepeatable(
            animation = tween(2000, easing = LinearEasing)
        ),
        label = "rotation"
    )

    val primaryColor = MaterialTheme.colorScheme.primary
    val trackColor = MaterialTheme.colorScheme.surfaceVariant

    Canvas(
        modifier = modifier
            .size(120.dp)
            .rotate(rotation)
    ) {
        val strokeWidth = 12.dp.toPx()
        val radius = (size.minDimension - strokeWidth) / 2

        // Background circle (track)
        drawCircle(
            color = trackColor,
            radius = radius,
            style = Stroke(width = strokeWidth, cap = StrokeCap.Round)
        )

        // Animated progress arc
        drawArc(
            color = primaryColor,
            startAngle = -90f,
            sweepAngle = animatedProgress * 360f,
            useCenter = false,
            style = Stroke(width = strokeWidth, cap = StrokeCap.Round),
            topLeft = Offset(strokeWidth / 2, strokeWidth / 2),
            size = Size(radius * 2, radius * 2)
        )
    }
}

āļžāļĢāđ‰āļ­āļĄāļ—āļĩāđˆāļˆāļ°āļžāļīāļŠāļīāļ•āļāļēāļĢāļŠāļąāļĄāļ āļēāļĐāļ“āđŒ Android āđāļĨāđ‰āļ§āļŦāļĢāļ·āļ­āļĒāļąāļ‡āļ„āļĢāļąāļš?

āļāļķāļāļāļ™āļ”āđ‰āļ§āļĒāļ•āļąāļ§āļˆāļģāļĨāļ­āļ‡āđāļšāļšāđ‚āļ•āđ‰āļ•āļ­āļš, flashcards āđāļĨāļ°āđāļšāļšāļ—āļ”āļŠāļ­āļšāđ€āļ—āļ„āļ™āļīāļ„āļ„āļĢāļąāļš

āļāļēāļĢāđ€āļžāļīāđˆāļĄāļ›āļĢāļ°āļŠāļīāļ—āļ˜āļīāļ āļēāļžāđāļ­āļ™āļīāđ€āļĄāļŠāļąāļ™

āđāļ­āļ™āļīāđ€āļĄāļŠāļąāļ™āļ—āļĩāđˆāļ›āļĢāļąāļšāđāļ•āđˆāļ‡āđ„āļĄāđˆāļ”āļĩāļ­āļēāļˆāļ—āļģāđƒāļŦāđ‰āđ€āļāļīāļ”āļ­āļēāļāļēāļĢāļāļĢāļ°āļ•āļļāļ (jank) āđāļĨāļ°āļ—āļģāđƒāļŦāđ‰āđāļšāļ•āđ€āļ•āļ­āļĢāļĩāđˆāļŦāļĄāļ”āđ€āļĢāđ‡āļ§ āļ™āļĩāđˆāļ„āļ·āļ­āđāļ™āļ§āļ—āļēāļ‡āļ›āļāļīāļšāļąāļ•āļīāļ—āļĩāđˆāļ”āļĩāļ—āļĩāđˆāļŠāļļāļ”āđƒāļ™āļāļēāļĢāļĢāļąāļāļĐāļē 60 FPS

āļāļŽāļ‚āđ‰āļ­āđāļĢāļāļ„āļ·āļ­āļŦāļĨāļĩāļāđ€āļĨāļĩāđˆāļĒāļ‡āļāļēāļĢāļˆāļąāļ”āļŠāļĢāļĢāļŦāļ™āđˆāļ§āļĒāļ„āļ§āļēāļĄāļˆāļģāļĢāļ°āļŦāļ§āđˆāļēāļ‡āđāļ­āļ™āļīāđ€āļĄāļŠāļąāļ™ āļ„āļ§āļĢāđƒāļŠāđ‰ graphicsLayer āđāļ—āļ™ modifier āļ—āļĩāđˆāļāļĢāļ°āļ•āļļāđ‰āļ™āļāļēāļĢ recompose

PerformanceOptimization.ktkotlin
@Composable
fun OptimizedAnimatedCard(
    isExpanded: Boolean,
    modifier: Modifier = Modifier
) {
    val scale by animateFloatAsState(
        targetValue = if (isExpanded) 1.1f else 1f,
        label = "scale"
    )

    val alpha by animateFloatAsState(
        targetValue = if (isExpanded) 1f else 0.8f,
        label = "alpha"
    )

    Card(
        modifier = modifier
            // ✅ graphicsLayer: GPU modifications without recomposition
            .graphicsLayer {
                scaleX = scale
                scaleY = scale
                this.alpha = alpha
            }
        // ❌ Avoid: .scale(scale).alpha(alpha)
        // These modifiers trigger recompositions
    ) {
        Text("Card content")
    }
}

// Example with remembered lambda to avoid allocations
@Composable
fun OptimizedClickableItem(
    onClick: () -> Unit,
    content: @Composable () -> Unit
) {
    // ✅ Stable remembered lambda
    val interactionSource = remember { MutableInteractionSource() }

    Box(
        modifier = Modifier
            .clickable(
                interactionSource = interactionSource,
                indication = ripple(),
                onClick = onClick
            )
    ) {
        content()
    }
}

āļˆāļļāļ”āļŠāļģāļ„āļąāļāļĨāļģāļ”āļąāļšāļ—āļĩāđˆāļŠāļ­āļ‡āđ€āļāļĩāđˆāļĒāļ§āļ‚āđ‰āļ­āļ‡āļāļąāļšāđāļ­āļ™āļīāđ€āļĄāļŠāļąāļ™āđƒāļ™āļĢāļēāļĒāļāļēāļĢ āļ„āļ§āļĢāļˆāļģāļāļąāļ”āļˆāļģāļ™āļ§āļ™āđāļ­āļ™āļīāđ€āļĄāļŠāļąāļ™āļ—āļĩāđˆāđ€āļāļīāļ”āļ‚āļķāđ‰āļ™āļžāļĢāđ‰āļ­āļĄāļāļąāļ™āđāļĨāļ°āđƒāļŠāđ‰ derivedStateOf āļŠāļģāļŦāļĢāļąāļšāļāļēāļĢāļ„āļģāļ™āļ§āļ“āļ—āļĩāđˆāļ­āļ™āļļāļĄāļēāļ™āđ„āļ”āđ‰

ListPerformance.ktkotlin
@Composable
fun PerformantAnimatedList(
    items: List<Item>,
    modifier: Modifier = Modifier
) {
    // Calculate once whether the list is empty
    val isEmpty by remember {
        derivedStateOf { items.isEmpty() }
    }

    LazyColumn(modifier = modifier) {
        items(
            items = items,
            key = { it.id }
        ) { item ->
            // Lightweight animation only on initial appearance
            var hasAppeared by remember { mutableStateOf(false) }

            LaunchedEffect(Unit) {
                hasAppeared = true
            }

            val alpha by animateFloatAsState(
                targetValue = if (hasAppeared) 1f else 0f,
                animationSpec = tween(200),
                label = "itemAlpha"
            )

            ItemCard(
                item = item,
                modifier = Modifier.graphicsLayer { this.alpha = alpha }
            )
        }
    }
}

āļšāļ—āļŠāļĢāļļāļ›

āđāļ­āļ™āļīāđ€āļĄāļŠāļąāļ™āđƒāļ™ Jetpack Compose āļĄāļ­āļšāļ„āļ§āļēāļĄāļŠāļĄāļ”āļļāļĨāļĢāļ°āļŦāļ§āđˆāļēāļ‡āļ„āļ§āļēāļĄāļ‡āđˆāļēāļĒāđƒāļ™āļāļēāļĢāđƒāļŠāđ‰āļ‡āļēāļ™āđāļĨāļ°āļāļēāļĢāļ„āļ§āļšāļ„āļļāļĄāļ‚āļąāđ‰āļ™āļŠāļđāļ‡ āļ™āļĩāđˆāļ„āļ·āļ­āļ›āļĢāļ°āđ€āļ”āđ‡āļ™āļŠāļģāļ„āļąāļāļ—āļĩāđˆāļ„āļ§āļĢāļˆāļ”āļˆāļģ:

  • ✅ āđ€āļĨāļ·āļ­āļāļĢāļ°āļ”āļąāļš API āļ—āļĩāđˆāđ€āļŦāļĄāļēāļ°āļŠāļĄāļ•āļēāļĄāļ„āļ§āļēāļĄāļ‹āļąāļšāļ‹āđ‰āļ­āļ™ (AnimatedVisibility → animate*AsState → Animatable)
  • ✅ āđƒāļŠāđ‰ updateTransition āđ€āļžāļ·āđˆāļ­āļ›āļĢāļ°āļŠāļēāļ™āļŦāļĨāļēāļĒāđāļ­āļ™āļīāđ€āļĄāļŠāļąāļ™āļ—āļĩāđˆāđ€āļāļĩāđˆāļĒāļ§āļ‚āđ‰āļ­āļ‡āļāļąāļ™
  • ✅ āđ€āļĨāļ·āļ­āļ spring āļŠāļģāļŦāļĢāļąāļšāđāļ­āļ™āļīāđ€āļĄāļŠāļąāļ™āļ—āļĩāđˆāđ€āļ›āđ‡āļ™āļ˜āļĢāļĢāļĄāļŠāļēāļ•āļī āđāļĨāļ° tween āļŠāļģāļŦāļĢāļąāļšāļĢāļ°āļĒāļ°āđ€āļ§āļĨāļēāļ—āļĩāđˆāđāļĄāđˆāļ™āļĒāļģ
  • ✅ āļĢāļ°āļšāļļāļžāļēāļĢāļēāļĄāļīāđ€āļ•āļ­āļĢāđŒ key āļ—āļĩāđˆāđ€āļŠāļ–āļĩāļĒāļĢāđ€āļŠāļĄāļ­āļŠāļģāļŦāļĢāļąāļšāđāļ­āļ™āļīāđ€āļĄāļŠāļąāļ™āļĢāļēāļĒāļāļēāļĢ
  • ✅ āļ›āļĢāļąāļšāđāļ•āđˆāļ‡āļ”āđ‰āļ§āļĒ graphicsLayer āđ€āļžāļ·āđˆāļ­āļŦāļĨāļĩāļāđ€āļĨāļĩāđˆāļĒāļ‡āļāļēāļĢ recompose āļ—āļĩāđˆāđ„āļĄāđˆāļˆāļģāđ€āļ›āđ‡āļ™
  • ✅ āļ—āļ”āļŠāļ­āļšāđāļ­āļ™āļīāđ€āļĄāļŠāļąāļ™āļšāļ™āļ­āļļāļ›āļāļĢāļ“āđŒāļˆāļĢāļīāļ‡āđ€āļžāļ·āđˆāļ­āļĒāļ·āļ™āļĒāļąāļ™āļ›āļĢāļ°āļŠāļīāļ—āļ˜āļīāļ āļēāļž

āļāļēāļĢāđ€āļŠāļĩāđˆāļĒāļ§āļŠāļēāļāđāļ­āļ™āļīāđ€āļĄāļŠāļąāļ™ Compose āļ—āļģāđƒāļŦāđ‰āđāļ­āļ› Android āļĢāļ°āļ”āļąāļšāļĄāļ·āļ­āļ­āļēāļŠāļĩāļžāđāļ•āļāļ•āđˆāļēāļ‡āļˆāļēāļāļ—āļĩāđˆāļ­āļ·āđˆāļ™ āđ€āļ—āļ„āļ™āļīāļ„āđ€āļŦāļĨāđˆāļēāļ™āļĩāđ‰āļœāļŠāļĄāļœāļŠāļēāļ™āļāļąāļšāļāļēāļĢāđƒāļŦāđ‰āļ„āļ§āļēāļĄāļŠāļģāļ„āļąāļāļāļąāļšāļ›āļĢāļ°āļŠāļīāļ—āļ˜āļīāļ āļēāļž āļ—āļģāđƒāļŦāđ‰āļŠāļēāļĄāļēāļĢāļ–āļŠāļĢāđ‰āļēāļ‡āļ›āļĢāļ°āļŠāļšāļāļēāļĢāļ“āđŒāļœāļđāđ‰āđƒāļŠāđ‰āļ—āļĩāđˆāļĨāļ·āđˆāļ™āđ„āļŦāļĨāđāļĨāļ°āļ™āđˆāļēāļŠāļ™āđƒāļˆ

āđ€āļĢāļīāđˆāļĄāļāļķāļāļ‹āđ‰āļ­āļĄāđ€āļĨāļĒ!

āļ—āļ”āļŠāļ­āļšāļ„āļ§āļēāļĄāļĢāļđāđ‰āļ‚āļ­āļ‡āļ„āļļāļ“āļ”āđ‰āļ§āļĒāļ•āļąāļ§āļˆāļģāļĨāļ­āļ‡āļŠāļąāļĄāļ āļēāļĐāļ“āđŒāđāļĨāļ°āđāļšāļšāļ—āļ”āļŠāļ­āļšāđ€āļ—āļ„āļ™āļīāļ„āļ„āļĢāļąāļš

āđāļ—āđ‡āļ

#jetpack compose
#android
#animations
#kotlin
#ui

āđāļŠāļĢāđŒ

āļšāļ—āļ„āļ§āļēāļĄāļ—āļĩāđˆāđ€āļāļĩāđˆāļĒāļ§āļ‚āđ‰āļ­āļ‡

āļ„āļģāļ–āļēāļĄāļŠāļąāļĄāļ āļēāļĐāļ“āđŒ Jetpack Compose āļŠāļģāļŦāļĢāļąāļšāļ™āļąāļāļžāļąāļ’āļ™āļē Android

20 āļ„āļģāļ–āļēāļĄāļŠāļąāļĄāļ āļēāļĐāļ“āđŒ Jetpack Compose āļĒāļ­āļ”āļ™āļīāļĒāļĄāļ›āļĢāļ°āļˆāļģāļ›āļĩ 2026

20 āļ„āļģāļ–āļēāļĄāļŠāļąāļĄāļ āļēāļĐāļ“āđŒ Jetpack Compose āļ—āļĩāđˆāļžāļšāļšāđˆāļ­āļĒāļ—āļĩāđˆāļŠāļļāļ”: recomposition, āļāļēāļĢāļˆāļąāļ”āļāļēāļĢ state, navigation, āļ›āļĢāļ°āļŠāļīāļ—āļ˜āļīāļ āļēāļž āđāļĨāļ° pattern āļŠāļ–āļēāļ›āļąāļ•āļĒāļāļĢāļĢāļĄ āļžāļĢāđ‰āļ­āļĄāļ•āļąāļ§āļ­āļĒāđˆāļēāļ‡āđ‚āļ„āđ‰āļ”āļĨāļ°āđ€āļ­āļĩāļĒāļ”

āļ„āļģāļ–āļēāļĄāļŠāļąāļĄāļ āļēāļĐāļ“āđŒ Kotlin 2.3 Android 2026

Kotlin 2.3 āļŠāļģāļŦāļĢāļąāļš Android: Name-Based Destructuring, KMP āđāļĨāļ°āļ„āļģāļ–āļēāļĄāļŠāļąāļĄāļ āļēāļĐāļ“āđŒ 2026

āļ„āļģāļ–āļēāļĄāļŠāļąāļĄāļ āļēāļĐāļ“āđŒ Kotlin 2.3 āļŠāļģāļŦāļĢāļąāļšāļ™āļąāļāļžāļąāļ’āļ™āļē Android āđƒāļ™āļ›āļĩ 2026 āļ„āļĢāļ­āļšāļ„āļĨāļļāļĄ name-based destructuring, KMP, context parameters, Flow āđāļĨāļ° coroutines āļžāļĢāđ‰āļ­āļĄāļ•āļąāļ§āļ­āļĒāđˆāļēāļ‡āđ‚āļ„āđ‰āļ”

āļāļēāļĢāđ€āļ›āļĢāļĩāļĒāļšāđ€āļ—āļĩāļĒāļš architecture MVVM āđāļĨāļ° MVI āļŠāļģāļŦāļĢāļąāļš Android

MVVM vs MVI āļšāļ™ Android: āđ€āļĨāļ·āļ­āļ Architecture āđ„āļŦāļ™āļ”āļĩāđƒāļ™āļ›āļĩ 2026?

āđ€āļ›āļĢāļĩāļĒāļšāđ€āļ—āļĩāļĒāļš MVVM āđāļĨāļ° MVI āļšāļ™ Android āļ­āļĒāđˆāļēāļ‡āļĨāļ°āđ€āļ­āļĩāļĒāļ”: āļ‚āđ‰āļ­āļ”āļĩāļ‚āđ‰āļ­āđ€āļŠāļĩāļĒ āļāļĢāļ“āļĩāļāļēāļĢāđƒāļŠāđ‰āļ‡āļēāļ™ āđāļĨāļ°āļ„āļđāđˆāļĄāļ·āļ­āļ›āļāļīāļšāļąāļ•āļīāđƒāļ™āļāļēāļĢāđ€āļĨāļ·āļ­āļ architecture āļ—āļĩāđˆāđ€āļŦāļĄāļēāļ°āļŠāļĄāđƒāļ™āļ›āļĩ 2026