Compose-এ অ্যানিমেশন সম্পর্কে সংক্ষিপ্ত নির্দেশিকা

Compose-এ অনেক বিল্ট-ইন অ্যানিমেশন মেকানিজম আছে এবং কোনটি বেছে নিতে হবে তা জানা অত্যন্ত কঠিন হতে পারে। নিচে অ্যানিমেশনের সাধারণ ব্যবহারের তালিকা দেওয়া হল। আপনার জন্য উপলভ্য বিভিন্ন API বিকল্পের সম্পূর্ণ সেট সম্পর্কে আরও বিস্তারিত তথ্যের জন্য, সম্পূর্ণ Compose অ্যানিমেশন ডকুমেন্টেশন পড়ুন।

সাধারণ কম্পোজেবল প্রপার্টি অ্যানিমেট করুন

Compose সুবিধাজনক API প্রদান করে যা আপনাকে অনেক সাধারণ অ্যানিমেশন ব্যবহারের ক্ষেত্রে সমাধান করতে দেয়। এই বিভাগে দেখানো হয়েছে যে কীভাবে আপনি কম্পোজেবলের সাধারণ প্রপার্টি অ্যানিমেট করতে পারেন।

অ্যানিমেশন দেখানো / লুকানো

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

কোনও কম্পোজেবল লুকাতে বা দেখাতে AnimatedVisibility ব্যবহার করুন। AnimatedVisibility-এর ভিতরে থাকা বাচ্চারা তাদের নিজস্ব প্রবেশ বা প্রস্থান ট্রানজিশনের জন্য Modifier.animateEnterExit() ব্যবহার করতে পারে।

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
    // ...
}

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

কম্পোজেবলের দৃশ্যমানতা অ্যানিমেট করার আরেকটি বিকল্প হল animateFloatAsState ব্যবহার করে সময়ের সাথে সাথে আলফা অ্যানিমেট করা:

var visible by remember {
    mutableStateOf(true)
}
val animatedAlpha by animateFloatAsState(
    targetValue = if (visible) 1.0f else 0f,
    label = "alpha"
)
Box(
    modifier = Modifier
        .size(200.dp)
        .graphicsLayer {
            alpha = animatedAlpha
        }
        .clip(RoundedCornerShape(8.dp))
        .background(colorGreen)
        .align(Alignment.TopCenter)
) {
}

তবে, আলফা পরিবর্তন করার সময় এই সতর্কতা মনে রাখতে হবে যে কম্পোজেবল কম্পোজিশনে থেকে যায় এবং এটি যে স্পেসে লে-আউট করা হয়েছে সেটি দখল করে থাকে। এর ফলে স্ক্রিন রিডার এবং অন্যান্য অ্যাক্সেসিবিলিটি মেকানিজম এখনও স্ক্রিনে আইটেমটি বিবেচনা করতে পারে। অন্যদিকে, AnimatedVisibility অবশেষে কম্পোজিশন থেকে আইটেমটি সরিয়ে দেয়।

কম্পোজেবলের আলফা অ্যানিমেট করা
ছবি ২. কম্পোজেবলের আলফা অ্যানিমেট করা

ব্যাকগ্রাউন্ডের রঙ অ্যানিমেট করুন

অ্যানিমেশন হিসেবে সময়ের সাথে সাথে ব্যাকগ্রাউন্ডের রঙ পরিবর্তন করার কম্পোজেবল, যেখানে রঙগুলি একে অপরের মধ্যে মিশে যাচ্ছে।
ছবি ৩. কম্পোজেবলের ব্যাকগ্রাউন্ডের রঙ অ্যানিমেট করা হচ্ছে

val animatedColor by animateColorAsState(
    if (animateBackgroundColor) colorGreen else colorBlue,
    label = "color"
)
Column(
    modifier = Modifier.drawBehind {
        drawRect(animatedColor)
    }
) {
    // your composable here
}

Modifier.background() ব্যবহার করার চেয়ে এই বিকল্পটি আরও বেশি কার্যকর। Modifier.background() ওয়ান-শট কালার সেটিংয়ের জন্য গ্রহণযোগ্য, তবে সময়ের সাথে সাথে কালার অ্যানিমেট করার সময়, এটি প্রয়োজনের চেয়ে বেশি রিকম্পোজিশনের কারণ হতে পারে।

ব্যাকগ্রাউন্ডের রঙে অসীম অ্যানিমেশন যোগ করতে, অ্যানিমেশন রিপিট করা বিভাগ দেখুন।

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

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

Compose আপনাকে কয়েকটি ভিন্ন উপায়ে কম্পোজেবলের সাইজ অ্যানিমেট করতে দেয়। কম্পোজেবল সাইজ পরিবর্তনের মধ্যে অ্যানিমেশনের জন্য animateContentSize() ব্যবহার করুন।

যেমন, আপনার কাছে যদি এমন একটি বক্স থাকে যাতে টেক্সট আছে যা এক থেকে একাধিক লাইনে প্রসারিত হতে পারে, তাহলে আপনি আরও মসৃণ ট্রানজিশন পেতে Modifier.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
        }

) {
}

এছাড়াও, আপনি SizeTransform-এর সাথে AnimatedContent ব্যবহার করে সাইজ কীভাবে পরিবর্তন করা উচিত তা বর্ণনা করতে পারেন।

কম্পোজেবলের পজিশন অ্যানিমেট করুন

সবুজ কম্পোজেবল মসৃণভাবে নিচে এবং ডানদিকে অ্যানিমেট করছে
ছবি ৫. অফসেট অনুযায়ী কম্পোজেবল সরানো হচ্ছে

কম্পোজেবলের পজিশন অ্যানিমেট করতে, Modifier.offset{ }-এর সাথে animateIntOffsetAsState() ব্যবহার করুন।

var moved by remember { mutableStateOf(false) }
val pxToMove = with(LocalDensity.current) {
    100.dp.toPx().roundToInt()
}
val offset by animateIntOffsetAsState(
    targetValue = if (moved) {
        IntOffset(pxToMove, pxToMove)
    } else {
        IntOffset.Zero
    },
    label = "offset"
)

Box(
    modifier = Modifier
        .offset {
            offset
        }
        .background(colorBlue)
        .size(100.dp)
        .clickable(
            interactionSource = remember { MutableInteractionSource() },
            indication = null
        ) {
            moved = !moved
        }
)

পজিশন বা সাইজ অ্যানিমেট করার সময় কম্পোজেবলগুলি যাতে অন্য কম্পোজেবলের উপরে বা নিচে আঁকা না হয় তা নিশ্চিত করতে চাইলে, Modifier.layout{ } ব্যবহার করুন। এই মডিফায়ার পেরেন্টে সাইজ ও পজিশন সংক্রান্ত পরিবর্তন প্রোপাগেট করে, যা পরে অন্যান্য চিলড্রেনকে প্রভাবিত করে।

যেমন, আপনি যদি Column-এর মধ্যে Box সরাতে চান এবং Box সরানোর সময় অন্য চাইল্ড সরাতে হয়, তাহলে Modifier.layout{ }-এর সাথে অফসেট সংক্রান্ত তথ্য নিম্নলিখিতভাবে অন্তর্ভুক্ত করুন:

var toggled by remember {
    mutableStateOf(false)
}
val interactionSource = remember {
    MutableInteractionSource()
}
Column(
    modifier = Modifier
        .padding(16.dp)
        .fillMaxSize()
        .clickable(indication = null, interactionSource = interactionSource) {
            toggled = !toggled
        }
) {
    val offsetTarget = if (toggled) {
        IntOffset(150, 150)
    } else {
        IntOffset.Zero
    }
    val offset = animateIntOffsetAsState(
        targetValue = offsetTarget, label = "offset"
    )
    Box(
        modifier = Modifier
            .size(100.dp)
            .background(colorBlue)
    )
    Box(
        modifier = Modifier
            .layout { measurable, constraints ->
                val offsetValue = if (isLookingAhead) offsetTarget else offset.value
                val placeable = measurable.measure(constraints)
                layout(placeable.width + offsetValue.x, placeable.height + offsetValue.y) {
                    placeable.placeRelative(offsetValue)
                }
            }
            .size(100.dp)
            .background(colorGreen)
    )
    Box(
        modifier = Modifier
            .size(100.dp)
            .background(colorBlue)
    )
}

২টি বক্সের মধ্যে ২য় বক্সটি তার X,Y পজিশন অ্যানিমেট করছে, ৩য় বক্সটি নিজেকে Y পরিমাণ সরিয়ে প্রতিক্রিয়া জানাচ্ছে।
ছবি ৬. Modifier.layout{ }-এর সাথে অ্যানিমেট করা হচ্ছে

কম্পোজেবলের প্যাডিং অ্যানিমেট করুন

ক্লিক করলে সবুজ কম্পোজেবল ছোট ও বড় হচ্ছে, সাথে প্যাডিং অ্যানিমেট করা হচ্ছে
ছবি ৭. প্যাডিং অ্যানিমেট করার সাথে কম্পোজেবল

কম্পোজেবলের প্যাডিং অ্যানিমেট করতে, animateDpAsState-এর সাথে Modifier.padding() ব্যবহার করুন:

var toggled by remember {
    mutableStateOf(false)
}
val animatedPadding by animateDpAsState(
    if (toggled) {
        0.dp
    } else {
        20.dp
    },
    label = "padding"
)
Box(
    modifier = Modifier
        .aspectRatio(1f)
        .fillMaxSize()
        .padding(animatedPadding)
        .background(Color(0xff53D9A1))
        .clickable(
            interactionSource = remember { MutableInteractionSource() },
            indication = null
        ) {
            toggled = !toggled
        }
)

কম্পোজেবলের এলিভেশন অ্যানিমেট করুন

ছবি ৮. ক্লিক করার সময় Composable-এর এলিভেশন অ্যানিমেট করা হচ্ছে

কম্পোজেবলের এলিভেশন অ্যানিমেট করতে, animateDpAsState-এর সাথে Modifier.graphicsLayer{ } ব্যবহার করুন। একবার উচ্চতা পরিবর্তন করতে, Modifier.shadow() ব্যবহার করুন। আপনি যদি শ্যাডো অ্যানিমেট করেন, তাহলে Modifier.graphicsLayer{ } মডিফায়ার ব্যবহার করা আরও বেশি পারফর্ম্যান্সের বিকল্প।

val mutableInteractionSource = remember {
    MutableInteractionSource()
}
val pressed = mutableInteractionSource.collectIsPressedAsState()
val elevation = animateDpAsState(
    targetValue = if (pressed.value) {
        32.dp
    } else {
        8.dp
    },
    label = "elevation"
)
Box(
    modifier = Modifier
        .size(100.dp)
        .align(Alignment.Center)
        .graphicsLayer {
            this.shadowElevation = elevation.value.toPx()
        }
        .clickable(interactionSource = mutableInteractionSource, indication = null) {
        }
        .background(colorGreen)
) {
}

বিকল্প হিসেবে, Card কম্পোজেবল ব্যবহার করুন এবং প্রতিটি স্টেট অনুযায়ী এলিভেশন প্রপার্টি আলাদা আলাদা ভ্যালুতে সেট করুন।

টেক্সট স্কেল, অনুবাদ বা রোটেশন অ্যানিমেট করুন

টেক্সট কম্পোজেবল হ্যালো বলছে, ছোট এবং বড় সাইজের মধ্যে অ্যানিমেট করছে।
ছবি ৯. দুটি সাইজের মধ্যে টেক্সট অ্যানিমেট করা হচ্ছে

টেক্সটের স্কেল, অনুবাদ বা রোটেশন অ্যানিমেট করার সময়, TextStyle-এ textMotion প্যারামিটার TextMotion.Animated-এ সেট করুন। এটি টেক্সট অ্যানিমেশনের মধ্যে আরও মসৃণ ট্রানজিশন নিশ্চিত করে। টেক্সট অনুবাদ, রোটেট বা স্কেল করতে Modifier.graphicsLayer{ } ব্যবহার করুন।

val infiniteTransition = rememberInfiniteTransition(label = "infinite transition")
val scale by infiniteTransition.animateFloat(
    initialValue = 1f,
    targetValue = 8f,
    animationSpec = infiniteRepeatable(tween(1000), RepeatMode.Reverse),
    label = "scale"
)
Box(modifier = Modifier.fillMaxSize()) {
    Text(
        text = "Hello",
        modifier = Modifier
            .graphicsLayer {
                scaleX = scale
                scaleY = scale
                transformOrigin = TransformOrigin.Center
            }
            .align(Alignment.Center),
        // Text composable does not take TextMotion as a parameter.
        // Provide it via style argument but make sure that we are copying from current theme
        style = LocalTextStyle.current.copy(textMotion = TextMotion.Animated)
    )
}

টেক্সটের রঙ অ্যানিমেট করুন

Hello Compose শব্দটির রঙ সবুজ ও নীলের মধ্যে অ্যানিমেট করছে
ছবি ১০. অ্যানিমেটিং টেক্সটের রঙ দেখানোর উদাহরণ

টেক্সটের রঙ অ্যানিমেট করতে, BasicText কম্পোজেবলে color ল্যাম্বডা ব্যবহার করুন:

val infiniteTransition = rememberInfiniteTransition(label = "infinite transition")
val animatedColor by infiniteTransition.animateColor(
    initialValue = Color(0xFF60DDAD),
    targetValue = Color(0xFF4285F4),
    animationSpec = infiniteRepeatable(tween(1000), RepeatMode.Reverse),
    label = "color"
)

BasicText(
    text = "Hello Compose",
    color = {
        animatedColor
    },
    // ...
)

বিভিন্ন ধরনের কন্টেন্টের মধ্যে পাল্টানো

সবুজ স্ক্রিনে 'লোড হচ্ছে', নীল স্ক্রিনে 'লোড হয়েছে' এবং সাদা স্ক্রিনে 'সমস্যা হয়েছে' লেখা আছে, বিভিন্ন কম্পোজেবল একটি সাধারণ অ্যানিমেশনের মাধ্যমে একে অপরের মধ্যে পরিবর্তন করা হচ্ছে।
ছবি ১১. বিভিন্ন কম্পোজেবলের মধ্যে পরিবর্তন অ্যানিমেট করতে AnimatedContent ব্যবহার করা (স্লো ডাউন করা)

বিভিন্ন কম্পোজেবলের মধ্যে অ্যানিমেট করতে AnimatedContent ব্যবহার করুন, আপনি যদি কম্পোজেবলের মধ্যে শুধু স্ট্যান্ডার্ড ফেড চান, তাহলে Crossfade ব্যবহার করুন।

var state by remember {
    mutableStateOf(UiState.Loading)
}
AnimatedContent(
    state,
    transitionSpec = {
        fadeIn(
            animationSpec = tween(3000)
        ) togetherWith fadeOut(animationSpec = tween(3000))
    },
    modifier = Modifier.clickable(
        interactionSource = remember { MutableInteractionSource() },
        indication = null
    ) {
        state = when (state) {
            UiState.Loading -> UiState.Loaded
            UiState.Loaded -> UiState.Error
            UiState.Error -> UiState.Loading
        }
    },
    label = "Animated Content"
) { targetState ->
    when (targetState) {
        UiState.Loading -> {
            LoadingScreen()
        }
        UiState.Loaded -> {
            LoadedScreen()
        }
        UiState.Error -> {
            ErrorScreen()
        }
    }
}

AnimatedContent-কে কাস্টমাইজ করে বিভিন্ন ধরনের এন্টার ও এক্সিট ট্রানজিশন দেখানো যেতে পারে। আরও তথ্যের জন্য, AnimatedContent-এর ডকুমেন্টেশন পড়ুন অথবা AnimatedContent-এর ব্লগ পোস্ট পড়ুন।

বিভিন্ন গন্তব্যে নেভিগেট করার সময় অ্যানিমেট করুন

দুটি কম্পোজ করার উপযুক্ত আইটেম, একটি সবুজ রঙের যাতে ল্যান্ডিং লেখা আছে এবং একটি নীল রঙের যাতে বিবরণ লেখা আছে, ল্যান্ডিং কম্পোজ করার উপযুক্ত আইটেমের উপর বিবরণ কম্পোজ করার উপযুক্ত আইটেম স্লাইড করে অ্যানিমেট করা হচ্ছে।
ছবি ১২. navigation-compose ব্যবহার করে কম্পোজেবলের মধ্যে অ্যানিমেট করা

navigation-compose আর্টিফ্যাক্ট ব্যবহার করার সময় কম্পোজেবলের মধ্যে ট্রানজিশন অ্যানিমেট করতে, কম্পোজেবলে enterTransition এবং exitTransition নির্দিষ্ট করুন। এছাড়াও, আপনি টপ লেভেলে NavHost সব গন্তব্যের জন্য ব্যবহার করার জন্য ডিফল্ট অ্যানিমেশন সেট করতে পারেন:

val navController = rememberNavController()
NavHost(
    navController = navController, startDestination = "landing",
    enterTransition = { EnterTransition.None },
    exitTransition = { ExitTransition.None }
) {
    composable("landing") {
        ScreenLanding(
            // ...
        )
    }
    composable(
        "detail/{photoUrl}",
        arguments = listOf(navArgument("photoUrl") { type = NavType.StringType }),
        enterTransition = {
            fadeIn(
                animationSpec = tween(
                    300, easing = LinearEasing
                )
            ) + slideIntoContainer(
                animationSpec = tween(300, easing = EaseIn),
                towards = AnimatedContentTransitionScope.SlideDirection.Start
            )
        },
        exitTransition = {
            fadeOut(
                animationSpec = tween(
                    300, easing = LinearEasing
                )
            ) + slideOutOfContainer(
                animationSpec = tween(300, easing = EaseOut),
                towards = AnimatedContentTransitionScope.SlideDirection.End
            )
        }
    ) { backStackEntry ->
        ScreenDetails(
            // ...
        )
    }
}

বিভিন্ন ধরনের এন্টার ও এক্সিট ট্রানজিশন আছে যা ইনকামিং ও আউটগোয়িং কন্টেন্টে বিভিন্ন এফেক্ট প্রয়োগ করে, আরও জানতে ডকুমেন্টেশন দেখুন।

অ্যানিমেশন রিপিট করা

একটি সবুজ ব্যাকগ্রাউন্ড যা দুটি রঙের মধ্যে অ্যানিমেট করে অসীমভাবে একটি নীল ব্যাকগ্রাউন্ডে রূপান্তরিত হয়।
ছবি ১৩. ব্যাকগ্রাউন্ড কালার দুটি মানের মধ্যে অ্যানিমেট করছে, অসীমভাবে

আপনার অ্যানিমেশন ক্রমাগত রিপিট করতে infiniteRepeatable animationSpec-এর সাথে rememberInfiniteTransition ব্যবহার করুন। RepeatModes পরিবর্তন করে এটি কীভাবে আগে ও পরে যাবে তা নির্দিষ্ট করুন।

নির্দিষ্ট সংখ্যক বার রিপিট করতে repeatable ব্যবহার করুন।

val infiniteTransition = rememberInfiniteTransition(label = "infinite")
val color by infiniteTransition.animateColor(
    initialValue = Color.Green,
    targetValue = Color.Blue,
    animationSpec = infiniteRepeatable(
        animation = tween(1000, easing = LinearEasing),
        repeatMode = RepeatMode.Reverse
    ),
    label = "color"
)
Column(
    modifier = Modifier.drawBehind {
        drawRect(color)
    }
) {
    // your composable here
}

কম্পোজেবল লঞ্চ করার সময় অ্যানিমেশন শুরু করুন

কম্পোজিশনে কম্পোজ করার উপযুক্ত আইটেম প্রবেশ করলে LaunchedEffect রান করে। এটি কম্পোজেবল লঞ্চ করার সময় অ্যানিমেশন শুরু করে, আপনি অ্যানিমেশন স্টেট পরিবর্তন করতে এটি ব্যবহার করতে পারেন। লঞ্চ করার সময় অ্যানিমেশন শুরু করতে animateTo পদ্ধতির সাথে Animatable ব্যবহার করা:

val alphaAnimation = remember {
    Animatable(0f)
}
LaunchedEffect(Unit) {
    alphaAnimation.animateTo(1f)
}
Box(
    modifier = Modifier.graphicsLayer {
        alpha = alphaAnimation.value
    }
)

সিকোয়েন্সিয়াল অ্যানিমেশন তৈরি করুন

চারটি বৃত্তের মধ্যে সবুজ রঙের তীরচিহ্ন রয়েছে, যা একটির পর একটি অ্যানিমেট করছে।
ছবি ১৪. সিকোয়েন্সিয়াল অ্যানিমেশন কীভাবে এক এক করে এগোয় তা ডায়াগ্রামের মাধ্যমে দেখানো হয়েছে।

সিকোয়েন্সিয়াল বা কনকারেন্ট অ্যানিমেশন পারফর্ম করতে Animatable coroutine API ব্যবহার করুন। Animatable-এ একের পর এক animateTo কল করলে, প্রতিটি অ্যানিমেশন আগের অ্যানিমেশন শেষ হওয়ার জন্য অপেক্ষা করে। এটি হওয়ার কারণ হল, এটি একটি সাসপেন্ড ফাংশন।

val alphaAnimation = remember { Animatable(0f) }
val yAnimation = remember { Animatable(0f) }

LaunchedEffect("animationKey") {
    alphaAnimation.animateTo(1f)
    yAnimation.animateTo(100f)
    yAnimation.animateTo(500f, animationSpec = tween(100))
}

কনকারেন্ট অ্যানিমেশন তৈরি করুন

তিনটি বৃত্তের প্রতিটিতে সবুজ তীর অ্যানিমেট করছে, সবকটি একসাথে একই সময়ে অ্যানিমেট করছে।
ছবি ১৫. একই সময়ে একাধিক অ্যানিমেশন কীভাবে একসাথে প্রোগ্রেস করে তা এই ডায়াগ্রামে দেখানো হয়েছে।

একসাথে অ্যানিমেশন চালানোর জন্য coroutine API (Animatable#animateTo() বা animate) অথবা Transition API ব্যবহার করুন। আপনি যদি একটি কোরুটিন প্রসঙ্গে একাধিক লঞ্চ ফাংশন ব্যবহার করেন, তাহলে এটি একই সময়ে অ্যানিমেশনগুলি লঞ্চ করে:

val alphaAnimation = remember { Animatable(0f) }
val yAnimation = remember { Animatable(0f) }

LaunchedEffect("animationKey") {
    launch {
        alphaAnimation.animateTo(1f)
    }
    launch {
        yAnimation.animateTo(100f)
    }
}

আপনি updateTransition API ব্যবহার করে একই সাথে অনেক আলাদা প্রপার্টি অ্যানিমেশন ড্রাইভ করার জন্য একই স্টেট ব্যবহার করতে পারবেন। নিম্নলিখিত উদাহরণে স্টেট পরিবর্তনের মাধ্যমে নিয়ন্ত্রিত দুটি প্রপার্টি অ্যানিমেট করা হয়েছে, rect এবং borderWidth:

var currentState by remember { mutableStateOf(BoxState.Collapsed) }
val transition = updateTransition(currentState, label = "transition")

val rect by transition.animateRect(label = "rect") { state ->
    when (state) {
        BoxState.Collapsed -> Rect(0f, 0f, 100f, 100f)
        BoxState.Expanded -> Rect(100f, 100f, 300f, 300f)
    }
}
val borderWidth by transition.animateDp(label = "borderWidth") { state ->
    when (state) {
        BoxState.Collapsed -> 1.dp
        BoxState.Expanded -> 0.dp
    }
}

অ্যানিমেশন পারফর্ম্যান্স অপ্টিমাইজ করুন

Compose-এ অ্যানিমেশন পারফর্ম্যান্স সংক্রান্ত সমস্যা সৃষ্টি করতে পারে। অ্যানিমেশনের ধরনই হল এমন: স্ক্রিনে পিক্সেল দ্রুত সরানো বা পরিবর্তন করা, ফ্রেম-বাই-ফ্রেম মুভমেন্টের বিভ্রম তৈরি করা।

Compose-এর বিভিন্ন ফেজ বিবেচনা করুন: কম্পোজিশন, লেআউট ও ড্র। আপনার অ্যানিমেশন লেআউট ফেজ পরিবর্তন করলে, প্রভাবিত সব কম্পোজেবলকে আবার লেআউট ও ড্র করতে হবে। আপনার অ্যানিমেশন ড্র ফেজে হলে, এটি ডিফল্ট হিসেবে লেআউট ফেজে অ্যানিমেশন চালানোর চেয়ে বেশি পারফর্ম করে, কারণ সামগ্রিকভাবে এতে কম কাজ করতে হয়।

অ্যানিমেশন চলাকালীন আপনার অ্যাপ যাতে যতটা সম্ভব কম কাজ করে তা নিশ্চিত করতে, যেখানে সম্ভব সেখানে Modifier-এর ল্যাম্বডা ভার্সন বেছে নিন। এটি রিকম্পোজিশন এড়িয়ে যায় এবং কম্পোজিশন ফেজের বাইরে অ্যানিমেশন পারফর্ম করে, অন্যথায় Modifier.graphicsLayer{ } ব্যবহার করুন, কারণ এই মডিফায়ার সবসময় ড্র ফেজে রান করে। এই বিষয়ে আরও তথ্যের জন্য, পারফর্ম্যান্স ডকুমেন্টেশনের রিড ডিফার করা বিভাগটি দেখুন।

অ্যানিমেশন টাইমিং পরিবর্তন করা

Compose বেশিরভাগ অ্যানিমেশনের জন্য ডিফল্ট হিসেবে স্প্রিং অ্যানিমেশন ব্যবহার করে। স্প্রিং বা পদার্থবিদ্যা-ভিত্তিক অ্যানিমেশন, আরও স্বাভাবিক মনে হয়। এগুলি বাধাগ্রস্তও হতে পারে কারণ এগুলি নির্দিষ্ট সময়ের পরিবর্তে অবজেক্টের বর্তমান বেগ বিবেচনা করে। আপনি যদি ডিফল্ট ওভাররাইড করতে চান, তাহলে আগে দেখানো সমস্ত অ্যানিমেশন API-এর কাছে একটি animationSpec সেট করার ক্ষমতা আছে যাতে একটি অ্যানিমেশন কীভাবে চলে তা কাস্টমাইজ করা যায়, আপনি এটি একটি নির্দিষ্ট সময়কাল ধরে চালাতে চান বা আরও বাউন্সি করতে চান।

নিচে বিভিন্ন animationSpec বিকল্পের সারসংক্ষেপ দেওয়া হল:

  • spring: পদার্থবিদ্যা-ভিত্তিক অ্যানিমেশন, সব অ্যানিমেশনের জন্য ডিফল্ট। আপনি অ্যানিমেশনের লুক ও ফিল পরিবর্তন করতে stiffness বা dampingRatio পরিবর্তন করতে পারেন।
  • tween (between-এর সংক্ষিপ্ত রূপ): সময়কাল-ভিত্তিক অ্যানিমেশন, Easing ফাংশন ব্যবহার করে দুটি মানের মধ্যে অ্যানিমেট করে।
  • keyframes: অ্যানিমেশনের নির্দিষ্ট কিছু কী পয়েন্টে ভ্যালু নির্দিষ্ট করার জন্য স্পেসিফিকেশন।
  • repeatable: সময়সীমা-ভিত্তিক স্পেসিফিকেশন যা নির্দিষ্ট সংখ্যক বার চলে, RepeatMode দ্বারা নির্দিষ্ট করা হয়।
  • infiniteRepeatable: সময়সীমা-ভিত্তিক স্পেসিফিকেশন যা চিরকাল চলে।
  • snap: কোনও অ্যানিমেশন ছাড়াই শেষ ভ্যালুতে ঝটপট স্ন্যাপ করে।
দুটি অ্যানিমেশন দেখানো হয়েছে, একটিতে কোনও স্পেক সেট নেই এবং অন্যটিতে কাস্টম Spring স্পেক সেট রয়েছে।
ছবি ১৬. কোনও স্পেক সেট বনাম কাস্টম স্প্রিং স্পেক সেট

animationSpecs সম্পর্কে আরও তথ্যের জন্য সম্পূর্ণ ডকুমেন্টেশন পড়ুন।

অতিরিক্ত রিসোর্স

Compose-এ মজাদার অ্যানিমেশনের আরও উদাহরণের জন্য, নিম্নলিখিতগুলি দেখুন: