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

একটি Composable লুকাতে বা দেখানোর জন্য AnimatedVisibility ব্যবহার করুন। AnimatedVisibility ভিতরে থাকা শিশুরা তাদের নিজস্ব enter বা exit ট্রানজিশনের জন্য 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() এক-শট রঙ সেটিংয়ের জন্য গ্রহণযোগ্য, কিন্তু সময়ের সাথে সাথে একটি রঙ অ্যানিমেট করার সময়, এটি প্রয়োজনের চেয়ে বেশি পুনর্গঠনের কারণ হতে পারে।
পটভূমির রঙ অসীমভাবে অ্যানিমেট করার জন্য, অ্যানিমেশনের পুনরাবৃত্তি বিভাগটি দেখুন।
একটি কম্পোজেবলের আকার অ্যানিমেট করুন

কম্পোজ আপনাকে কয়েকটি ভিন্ন উপায়ে কম্পোজেবলের আকার অ্যানিমেট করতে দেয়। কম্পোজেবল আকার পরিবর্তনের মধ্যে অ্যানিমেশনের জন্য 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 ব্যবহার করতে পারেন।
কম্পোজেবলের অবস্থান অ্যানিমেট করুন

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

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 } )
একটি কম্পোজেবলের উচ্চতা অ্যানিমেট করুন
একটি কম্পোজেবলের উচ্চতা অ্যানিমেট করতে, 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) ) }
টেক্সটের রঙ অ্যানিমেট করুন

টেক্সটের রঙ অ্যানিমেট করতে, 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 ব্যবহার করুন, যদি আপনি কেবল কম্পোজেবলের মধ্যে একটি স্ট্যান্ডার্ড ফেইড চান, তাহলে 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 এর এই ব্লগ পোস্টটি পড়ুন।
বিভিন্ন গন্তব্যে নেভিগেট করার সময় অ্যানিমেট করুন

নেভিগেশন-কম্পোজ আর্টিফ্যাক্ট ব্যবহার করার সময় কম্পোজেবলের মধ্যে ট্রানজিশন অ্যানিমেট করতে, একটি কম্পোজেবলে 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 ব্যবহার করুন। যদি আপনি একটি coroutine প্রসঙ্গে একাধিক লঞ্চ ফাংশন ব্যবহার করেন, তাহলে এটি একই সময়ে অ্যানিমেশনগুলি চালু করবে:
val alphaAnimation = remember { Animatable(0f) } val yAnimation = remember { Animatable(0f) } LaunchedEffect("animationKey") { launch { alphaAnimation.animateTo(1f) } launch { yAnimation.animateTo(100f) } }
একই সময়ে অনেকগুলি ভিন্ন ভিন্ন প্রপার্টি অ্যানিমেশন চালানোর জন্য আপনি updateTransition API ব্যবহার করতে পারেন। নিচের উদাহরণটি দুটি প্রপার্টি অ্যানিমেট করে যা state change দ্বারা নিয়ন্ত্রিত হয়, 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 } }
অ্যানিমেশন কর্মক্ষমতা অপ্টিমাইজ করুন
কম্পোজে অ্যানিমেশনের কারণে পারফরম্যান্সের সমস্যা হতে পারে। এটি অ্যানিমেশনের প্রকৃতির কারণে: স্ক্রিনে পিক্সেল দ্রুত সরানো বা পরিবর্তন করা, ফ্রেম-বাই-ফ্রেম নড়াচড়ার মায়া তৈরি করা।
কম্পোজের বিভিন্ন ধাপ বিবেচনা করুন: কম্পোজিশন, লেআউট এবং ড্র। যদি আপনার অ্যানিমেশন লেআউট ফেজ পরিবর্তন করে, তাহলে সমস্ত প্রভাবিত কম্পোজেবল রিলেআউট এবং রিড্রয় করতে হবে। যদি আপনার অ্যানিমেশন ড্র ফেজে হয়, তাহলে এটি ডিফল্টভাবে লেআউট ফেজে অ্যানিমেশন চালানোর চেয়ে বেশি পারফর্মেন্সিভ হবে, কারণ এতে সামগ্রিকভাবে কম কাজ করতে হবে।
অ্যানিমেটিং করার সময় আপনার অ্যাপটি যতটা সম্ভব কম কাজ করে তা নিশ্চিত করার জন্য, সম্ভব হলে Modifier এর lambda সংস্করণটি বেছে নিন। এটি রিকম্পোজিশন এড়িয়ে যায় এবং কম্পোজিশন পর্বের বাইরে অ্যানিমেশন সম্পাদন করে, অন্যথায় Modifier.graphicsLayer{ } ব্যবহার করুন, কারণ এই মডিফায়ারটি সর্বদা ড্র পর্বে চলে। এই সম্পর্কে আরও তথ্যের জন্য, পারফরম্যান্স ডকুমেন্টেশনের ডিফারিং রিডস বিভাগটি দেখুন।
অ্যানিমেশনের সময় পরিবর্তন করুন
বেশিরভাগ অ্যানিমেশনের জন্য ডিফল্টভাবে কম্পোজ স্প্রিং অ্যানিমেশন ব্যবহার করে। স্প্রিং, অথবা পদার্থবিদ্যা-ভিত্তিক অ্যানিমেশনগুলি আরও স্বাভাবিক মনে হয়। নির্দিষ্ট সময়ের পরিবর্তে বস্তুর বর্তমান বেগ বিবেচনা করে এগুলি বাধাগ্রস্ত হয়। আপনি যদি ডিফল্টটি ওভাররাইড করতে চান, তাহলে উপরে প্রদর্শিত সমস্ত অ্যানিমেশন API গুলিতে একটি animationSpec সেট করার ক্ষমতা রয়েছে যাতে একটি অ্যানিমেশন কীভাবে চলে তা কাস্টমাইজ করা যায়, আপনি এটি একটি নির্দিষ্ট সময়কাল ধরে চালানোর জন্য চান বা আরও বাউন্সি হতে চান।
বিভিন্ন animationSpec বিকল্পগুলির সারসংক্ষেপ নিচে দেওয়া হল:
-
spring: পদার্থবিদ্যা-ভিত্তিক অ্যানিমেশন, সকল অ্যানিমেশনের জন্য ডিফল্ট। আপনি একটি ভিন্ন অ্যানিমেশন লুক এবং অনুভূতি অর্জনের জন্য কঠোরতা বা ড্যাম্পিং রেশিও পরিবর্তন করতে পারেন। -
tween(এর সংক্ষিপ্ত রূপ হল between ): সময়কাল-ভিত্তিক অ্যানিমেশন, একটিEasingফাংশনের সাহায্যে দুটি মানের মধ্যে অ্যানিমেট করে। -
keyframes: অ্যানিমেশনের নির্দিষ্ট কিছু গুরুত্বপূর্ণ পয়েন্টে মান নির্দিষ্ট করার জন্য স্পেসিফিকেশন। -
repeatable: সময়কাল-ভিত্তিক স্পেক যাRepeatModeদ্বারা নির্দিষ্ট সংখ্যক বার চালানো হয়। -
infiniteRepeatable: সময়কাল-ভিত্তিক স্পেক যা চিরকাল চলবে। -
snap: কোনও অ্যানিমেশন ছাড়াই তাৎক্ষণিকভাবে শেষ মানটিতে স্ন্যাপ করে।

অ্যানিমেশনস্পেক্স সম্পর্কে আরও তথ্যের জন্য সম্পূর্ণ ডকুমেন্টেশনটি পড়ুন।
অতিরিক্ত সম্পদ
কম্পোজে মজাদার অ্যানিমেশনের আরও উদাহরণের জন্য, নিম্নলিখিতগুলি দেখুন:
- কম্পোজে ৫টি দ্রুত অ্যানিমেশন
- কম্পোজে জেলিফিশকে স্থানান্তরিত করা
- কম্পোজে
AnimatedContentকাস্টমাইজ করা - কম্পোজে সহজীকরণ ফাংশনে সহজীকরণ