অ্যানিমেশন মডিফায়ার ও কম্পোজেবল

সাধারণ অ্যানিমেশন ব্যবহারের ক্ষেত্রগুলি ম্যানেজ করার জন্য Compose-এ বিল্ট-ইন কম্পোজেবল ও মডিফায়ার থাকে।

বিল্ট-ইন অ্যানিমেটেড কম্পোজেবল

Compose-এ বেশ কিছু কম্পোজেবল আছে যা কন্টেন্ট দেখানো, লুকানো এবং লেআউট পরিবর্তন করার অ্যানিমেশন তৈরি করে।

দৃশ্যমান ও অদৃশ্য হওয়ার অ্যানিমেশন

সবুজ কম্পোজ করার মতো আইটেম নিজে থেকেই দেখা ও লুকানো
ছবি ১. কলামে কোনও আইটেম দেখানো ও লুকানোর অ্যানিমেশন।

এর কন্টেন্ট কীভাবে দেখা যাবে ও অদৃশ্য হবে তা AnimatedVisibility কম্পোজ করা যায়।

var visible by remember {
    mutableStateOf(true)
}
// Animated visibility will eventually remove the item from the composition once the animation has finished.
AnimatedVisibility(visible) {
    // your composable here
    // ...
}

সাধারণত, কন্টেন্ট ধীরে ধীরে দৃশ্যমান হয় এবং বড় হতে থাকে এবং ধীরে ধীরে অদৃশ্য হয়ে যায় এবং ছোট হতে থাকে। EnterTransition ও ExitTransition অবজেক্ট নির্দিষ্ট করার মাধ্যমে এই ট্রানজিশন কাস্টমাইজ করুন।

var visible by remember { mutableStateOf(true) }
val density = LocalDensity.current
AnimatedVisibility(
    visible = visible,
    enter = slideInVertically {
        // Slide in from 40 dp from the top.
        with(density) { -40.dp.roundToPx() }
    } + expandVertically(
        // Expand from the top.
        expandFrom = Alignment.Top
    ) + fadeIn(
        // Fade in with the initial alpha of 0.3f.
        initialAlpha = 0.3f
    ),
    exit = slideOutVertically() + shrinkVertically() + fadeOut()
) {
    Text(
        "Hello",
        Modifier
            .fillMaxWidth()
            .height(200.dp)
    )
}

আগের উদাহরণে দেখানো হয়েছে, আপনি + অপারেটরের সাহায্যে একাধিক EnterTransition বা ExitTransition অবজেক্ট একত্রিত করতে পারেন এবং প্রতিটি অবজেক্টের আচরণ কাস্টমাইজ করার জন্য ঐচ্ছিক প্যারামিটার গ্রহণ করে। আরও তথ্যের জন্য রেফারেন্স পৃষ্ঠা দেখুন।

এন্ট্রি ও এক্সিট ট্রানজিশনের উদাহরণ

EnterTransition ExitTransition
fadeIn
UI এলিমেন্ট ধীরে ধীরে দৃশ্যমান হয়।
fadeOut
UI এলিমেন্ট ধীরে ধীরে অদৃশ্য হয়ে যায়।
slideIn
স্ক্রিনের বাইরে থেকে একটি UI এলিমেন্ট স্লাইড করে স্ক্রিনে দেখা যাচ্ছে।
slideOut
UI এলিমেন্ট স্ক্রিনের বাইরে স্লাইড করে চলে যায়।
slideInHorizontally
একটি UI এলিমেন্ট অনুভূমিকভাবে স্লাইড করে ভিউতে আসে।
slideOutHorizontally
একটি UI এলিমেন্ট অনুভূমিকভাবে স্লাইড করে ভিউয়ের বাইরে চলে যায়।
slideInVertically
একটি UI এলিমেন্ট উল্লম্বভাবে স্লাইড করে ভিউতে আসে।
slideOutVertically
UI এলিমেন্ট উল্লম্বভাবে স্লাইড করে ভিউয়ের বাইরে চলে যায়।
scaleIn
UI এলিমেন্ট বড় হয়ে ভিউতে আসে।
scaleOut
UI এলিমেন্ট ছোট হয়ে যায় এবং আর দেখা যায় না।
expandIn
UI এলিমেন্ট একটি কেন্দ্রীয় বিন্দু থেকে প্রসারিত হয়ে দৃশ্যমান হয়।
shrinkOut
UI এলিমেন্ট ছোট হয়ে স্ক্রিনের কেন্দ্রবিন্দুতে চলে যায়।
expandHorizontally
একটি UI এলিমেন্ট অনুভূমিকভাবে বড় হয়ে দৃশ্যমান হয়।
shrinkHorizontally
একটি UI এলিমেন্ট অনুভূমিকভাবে ছোট হয়ে ভিউয়ের বাইরে চলে যায়।
expandVertically
UI এলিমেন্ট উল্লম্বভাবে প্রসারিত হয়ে দেখা যায়।
shrinkVertically
UI এলিমেন্ট উল্লম্বভাবে ছোট হয়ে দৃষ্টিসীমার বাইরে চলে যায়।

AnimatedVisibility-এর এমন একটি ভেরিয়েন্টও আছে যা MutableTransitionState আর্গুমেন্ট নেয়। এর ফলে, কম্পোজিশন ট্রি-তে AnimatedVisibility কম্পোজ করার উপযুক্ত আইটেম যোগ করার সাথে সাথেই আপনি অ্যানিমেশন ট্রিগার করতে পারবেন। এছাড়াও, এটি অ্যানিমেশন স্টেট পর্যবেক্ষণের জন্য উপযোগী।

// Create a MutableTransitionState<Boolean> for the AnimatedVisibility.
val state = remember {
    MutableTransitionState(false).apply {
        // Start the animation immediately.
        targetState = true
    }
}
Column {
    AnimatedVisibility(visibleState = state) {
        Text(text = "Hello, world!")
    }

    // Use the MutableTransitionState to know the current animation state
    // of the AnimatedVisibility.
    Text(
        text = when {
            state.isIdle && state.currentState -> "Visible"
            !state.isIdle && state.currentState -> "Disappearing"
            state.isIdle && !state.currentState -> "Invisible"
            else -> "Appearing"
        }
    )
}

বাচ্চাদের জন্য প্রবেশ ও বেরিয়ে আসার অ্যানিমেশন

AnimatedVisibility (সরাসরি বা পরোক্ষ চাইল্ড) কন্টেন্টের মধ্যে থাকা প্রতিটি কন্টেন্টের জন্য আলাদা আলাদা অ্যানিমেশন আচরণ নির্দিষ্ট করতে animateEnterExit মডিফায়ার ব্যবহার করা যেতে পারে। এইসব বাচ্চাদের প্রত্যেকটির জন্য ভিজ্যুয়াল ইফেক্ট হল AnimatedVisibility কম্পোজ করার উপযুক্ত এবং বাচ্চার নিজস্ব প্রবেশ ও বেরিয়ে যাওয়ার অ্যানিমেশনে নির্দিষ্ট করা অ্যানিমেশনের কম্বিনেশন।

var visible by remember { mutableStateOf(true) }

AnimatedVisibility(
    visible = visible,
    enter = fadeIn(),
    exit = fadeOut()
) {
    // Fade in/out the background and the foreground.
    Box(
        Modifier
            .fillMaxSize()
            .background(Color.DarkGray)
    ) {
        Box(
            Modifier
                .align(Alignment.Center)
                .animateEnterExit(
                    // Slide in/out the inner box.
                    enter = slideInVertically(),
                    exit = slideOutVertically()
                )
                .sizeIn(minWidth = 256.dp, minHeight = 64.dp)
                .background(Color.Red)
        ) {
            // Content of the notification…
        }
    }
}

কিছু ক্ষেত্রে, আপনি AnimatedVisibilityকোনও অ্যানিমেশন প্রয়োগ করতে নাও চান, যাতে বাচ্চারা প্রত্যেকে নিজেদের আলাদা আলাদা অ্যানিমেশন animateEnterExit ব্যবহার করতে পারে। এটি করতে, AnimatedVisibility কম্পোজ করার উপযুক্ত আইটেমে EnterTransition.None এবং ExitTransition.None নির্দিষ্ট করুন।

কাস্টম অ্যানিমেশন যোগ করা

বিল্ট-ইন এন্টার ও এক্সিট অ্যানিমেশন ছাড়াও কাস্টম অ্যানিমেশন এফেক্ট যোগ করতে চাইলে, AnimatedVisibility-এর জন্য কন্টেন্ট ল্যাম্বডার মধ্যে থাকা transition প্রপার্টি ব্যবহার করে অন্তর্নিহিত Transition ইনস্ট্যান্স অ্যাক্সেস করুন। Transition ইন্সট্যান্সে যোগ করা যেকোনও অ্যানিমেশন স্টেট, AnimatedVisibility-এর এন্টার ও এক্সিট অ্যানিমেশনের সাথে একসাথে চলবে। AnimatedVisibility অপেক্ষা করে যতক্ষণ না Transition-এর সব অ্যানিমেশন শেষ হয়ে যায়, তার আগে সেটির কন্টেন্ট সরিয়ে দেয় না। Transition-এর থেকে আলাদাভাবে তৈরি করা এক্সিট অ্যানিমেশনের (যেমন, animate*AsState ব্যবহার করে) ক্ষেত্রে, AnimatedVisibility সেগুলি বিবেচনা করতে পারবে না এবং তাই সেগুলি শেষ হওয়ার আগেই কন্টেন্ট কম্পোজ করার সুবিধা সরিয়ে দিতে পারে।

var visible by remember { mutableStateOf(true) }

AnimatedVisibility(
    visible = visible,
    enter = fadeIn(),
    exit = fadeOut()
) { // this: AnimatedVisibilityScope
    // Use AnimatedVisibilityScope#transition to add a custom animation
    // to the AnimatedVisibility.
    val background by transition.animateColor(label = "color") { state ->
        if (state == EnterExitState.Visible) Color.Blue else Color.Gray
    }
    Box(
        modifier = Modifier
            .size(128.dp)
            .background(background)
    )
}

অ্যানিমেশন ম্যানেজ করার জন্য Transition ব্যবহার করা সম্পর্কে আরও জানতে, ট্রানজিশনের মাধ্যমে একাধিক প্রপার্টি একসাথে অ্যানিমেট করা দেখুন।

টার্গেট স্টেটের উপর ভিত্তি করে অ্যানিমেট করা

AnimatedContent টার্গেট স্টেটের উপর ভিত্তি করে পরিবর্তন হওয়ার সাথে সাথে কম্পোজ করার উপযুক্ত কন্টেন্ট অ্যানিমেট করে।

Row {
    var count by remember { mutableIntStateOf(0) }
    Button(onClick = { count++ }) {
        Text("Add")
    }
    AnimatedContent(
        targetState = count,
        label = "animated content"
    ) { targetCount ->
        // Make sure to use `targetCount`, not `count`.
        Text(text = "Count: $targetCount")
    }
}

সাধারণত, প্রাথমিক কন্টেন্ট ফেড-আউট হয়ে যায় এবং তারপরে টার্গেট কন্টেন্ট ফেড-ইন হয় (এই আচরণকে ফেড থ্রু বলা হয়)। আপনি transitionSpec প্যারামিটারে ContentTransform অবজেক্ট নির্দিষ্ট করে এই অ্যানিমেশন আচরণ কাস্টমাইজ করতে পারবেন। আপনি ContentTransform-এর একটি ইনস্ট্যান্স তৈরি করতে পারেন, এর জন্য with ইনফিক্স ফাংশন ব্যবহার করে EnterTransition অবজেক্টের সাথে ExitTransition অবজেক্ট কম্বাইন করুন। আপনি using ইনফিক্স ফাংশনের মাধ্যমে ContentTransform অবজেক্টের সাথে এটি অ্যাটাচ করে SizeTransform প্রয়োগ করতে পারেন।

AnimatedContent(
    targetState = count,
    transitionSpec = {
        // Compare the incoming number with the previous number.
        if (targetState > initialState) {
            // If the target number is larger, it slides up and fades in
            // while the initial (smaller) number slides up and fades out.
            slideInVertically { height -> height } + fadeIn() togetherWith
                slideOutVertically { height -> -height } + fadeOut()
        } else {
            // If the target number is smaller, it slides down and fades in
            // while the initial number slides down and fades out.
            slideInVertically { height -> -height } + fadeIn() togetherWith
                slideOutVertically { height -> height } + fadeOut()
        }.using(
            // Disable clipping since the faded slide-in/out should
            // be displayed out of bounds.
            SizeTransform(clip = false)
        )
    }, label = "animated content"
) { targetCount ->
    Text(text = "$targetCount")
}

EnterTransition নির্ধারণ করে যে টার্গেট কন্টেন্টটি কেমন দেখতে হবে এবং ExitTransition নির্ধারণ করে যে প্রাথমিক কন্টেন্টটি কীভাবে অদৃশ্য হয়ে যাবে। AnimatedVisibility-এর জন্য উপলভ্য EnterTransition ও ExitTransition ফাংশন ছাড়াও AnimatedContent-এ slideIntoContainer ও slideOutOfContainer রয়েছে। এগুলি হল slideInHorizontally/Vertically এবং slideOutHorizontally/Vertically-এর সুবিধাজনক বিকল্প যা AnimatedContent কন্টেন্টের প্রাথমিক কন্টেন্ট ও টার্গেট কন্টেন্টের সাইজের উপর ভিত্তি করে স্লাইড দূরত্ব গণনা করে।

SizeTransform নির্ধারণ করে যে কীভাবে প্রাথমিক ও টার্গেট কন্টেন্টের মধ্যে সাইজ অ্যানিমেট করা উচিত। অ্যানিমেশন তৈরি করার সময় আপনার কাছে প্রাথমিক সাইজ ও টার্গেট সাইজ, দুটিই অ্যাক্সেস করার সুবিধা থাকে। SizeTransform এছাড়াও, অ্যানিমেশনের সময় কন্টেন্ট কম্পোনেন্টের সাইজ অনুযায়ী ক্লিপ করা উচিত কিনা তা নিয়ন্ত্রণ করে।

var expanded by remember { mutableStateOf(false) }
Surface(
    color = MaterialTheme.colorScheme.primary,
    onClick = { expanded = !expanded }
) {
    AnimatedContent(
        targetState = expanded,
        transitionSpec = {
            fadeIn(animationSpec = tween(150, 150)) togetherWith
                fadeOut(animationSpec = tween(150)) using
                SizeTransform { initialSize, targetSize ->
                    if (targetState) {
                        keyframes {
                            // Expand horizontally first.
                            IntSize(targetSize.width, initialSize.height) at 150
                            durationMillis = 300
                        }
                    } else {
                        keyframes {
                            // Shrink vertically first.
                            IntSize(initialSize.width, targetSize.height) at 150
                            durationMillis = 300
                        }
                    }
                }
        }, label = "size transform"
    ) { targetExpanded ->
        if (targetExpanded) {
            Expanded()
        } else {
            ContentIcon()
        }
    }
}

চাইল্ড এন্টার ও এক্সিট ট্রানজিশন অ্যানিমেট করা

AnimatedVisibility-এর মতো, animateEnterExit মডিফায়ার AnimatedContent-এর কন্টেন্ট ল্যাম্বডার মধ্যে উপলভ্য। প্রত্যক্ষ বা পরোক্ষ চাইল্ডের প্রত্যেকটিতে আলাদা আলাদাভাবে EnterAnimation ও ExitAnimation প্রয়োগ করতে এটি ব্যবহার করুন।

কাস্টম অ্যানিমেশন যোগ করা

AnimatedVisibility-এর মতো, transition ফিল্ডটি AnimatedContent-এর কন্টেন্ট ল্যাম্বডার মধ্যে উপলভ্য। AnimatedContent ট্রানজিশনের সাথে একই সাথে রান করে এমন কাস্টম অ্যানিমেশন এফেক্ট তৈরি করতে এটি ব্যবহার করুন। বিবরণের জন্য updateTransition দেখুন।

দুটি লেআউটের মধ্যে অ্যানিমেট করা

Crossfade ক্রসফেড অ্যানিমেশন সহ দুটি লেআউটের মধ্যে অ্যানিমেট করে। current প্যারামিটারে পাস করা ভ্যালু টগল করার মাধ্যমে, কন্টেন্টকে ক্রসফেড অ্যানিমেশন দিয়ে পরিবর্তন করা হয়।

var currentPage by remember { mutableStateOf("A") }
Crossfade(targetState = currentPage, label = "cross fade") { screen ->
    when (screen) {
        "A" -> Text("Page A")
        "B" -> Text("Page B")
    }
}

বিল্ট-ইন অ্যানিমেশন মডিফায়ার

কম্পোজ, কম্পোজ করার উপযুক্ত আইটেমে সরাসরি নির্দিষ্ট পরিবর্তন অ্যানিমেট করার জন্য মডিফায়ার প্রদান করে।

কম্পোজেবল সাইজ পরিবর্তন অ্যানিমেট করা

সবুজ কম্পোজ করার মতো অ্যানিমেশনটি মসৃণভাবে সাইজ পরিবর্তন করছে।
ছবি ২. ছোট ও বড় সাইজের মধ্যে মসৃণভাবে অ্যানিমেট করা যায় এমন কম্পোজ করার উপযুক্ত আইটেম

animateContentSize মডিফায়ার সাইজের পরিবর্তন অ্যানিমেট করে।

var expanded by remember { mutableStateOf(false) }
Box(
    modifier = Modifier
        .background(colorBlue)
        .animateContentSize()
        .height(if (expanded) 400.dp else 200.dp)
        .fillMaxWidth()
        .clickable(
            interactionSource = remember { MutableInteractionSource() },
            indication = null
        ) {
            expanded = !expanded
        }

) {
}

তালিকা আইটেম অ্যানিমেশন

আপনি যদি কোনও লেজি লিস্ট বা গ্রিডের মধ্যে আইটেম রিঅর্ডার করার অ্যানিমেশন করতে চান, তাহলে লেজি লেআউট আইটেম অ্যানিমেশন ডকুমেন্টেশন দেখুন।