এই পৃষ্ঠাটি জেটপ্যাক কম্পোজে মান-ভিত্তিক অ্যানিমেশন তৈরি করার পদ্ধতি বর্ণনা করে, যেখানে API গুলিকে কেন্দ্র করে মানগুলিকে তাদের বর্তমান এবং লক্ষ্য অবস্থার উপর ভিত্তি করে অ্যানিমেট করা হয়।
animate*AsState
দিয়ে একটি একক মান অ্যানিমেট করুন
animate*AsState
ফাংশনগুলি হল Compose-এ একটি একক মান অ্যানিমেট করার জন্য সহজবোধ্য অ্যানিমেশন API। আপনি কেবল লক্ষ্য মান (অথবা শেষ মান) প্রদান করেন এবং API বর্তমান মান থেকে নির্দিষ্ট মান পর্যন্ত অ্যানিমেশন শুরু করে।
নিচের উদাহরণটি এই API ব্যবহার করে আলফা অ্যানিমেট করে। animateFloatAsState
এ টার্গেট মানটি মোড়ানোর মাধ্যমে, আলফা মানটি এখন প্রদত্ত মানগুলির মধ্যে একটি অ্যানিমেশন মান (এই ক্ষেত্রে 1f
বা 0.5f
)।
var enabled by remember { mutableStateOf(true) } val animatedAlpha: Float by animateFloatAsState(if (enabled) 1f else 0.5f, label = "alpha") Box( Modifier .fillMaxSize() .graphicsLayer { alpha = animatedAlpha } .background(Color.Red) )
আপনাকে কোনও অ্যানিমেশন ক্লাসের ইনস্ট্যান্স তৈরি করতে হবে না বা ইন্টারাপ্টেশন হ্যান্ডেল করতে হবে না। হুডের নিচে, একটি অ্যানিমেশন অবজেক্ট (যেমন, একটি Animatable
ইনস্ট্যান্স) তৈরি করা হবে এবং কল সাইটে মনে রাখা হবে, যার প্রাথমিক মান প্রথম টার্গেট মান হিসাবে থাকবে। সেখান থেকে, আপনি যখনই এই কম্পোজেবলকে একটি ভিন্ন টার্গেট মান সরবরাহ করবেন, তখনই একটি অ্যানিমেশন স্বয়ংক্রিয়ভাবে সেই মানের দিকে শুরু হবে। যদি ইতিমধ্যেই কোনও অ্যানিমেশন ফ্লাইটে থাকে, তাহলে অ্যানিমেশনটি তার বর্তমান মান (এবং বেগ) থেকে শুরু হয় এবং টার্গেট মানের দিকে অ্যানিমেট হয়। অ্যানিমেশনের সময়, এই কম্পোজেবলটি পুনরায় কম্পোজ করা হয় এবং প্রতিটি ফ্রেমে একটি আপডেট করা অ্যানিমেশন মান প্রদান করে।
ডিফল্টরূপে, Compose Float
, Color
, Dp
, Size
, Offset
, Rect
, Int
, IntOffset
, এবং IntSize
এর জন্য animate*AsState
ফাংশন প্রদান করে। আপনি animateValueAsState
এ একটি TwoWayConverter
প্রদান করে অন্যান্য ডেটা টাইপের জন্য সমর্থন যোগ করতে পারেন যা একটি জেনেরিক টাইপ নেয়।
আপনি একটি AnimationSpec
প্রদান করে অ্যানিমেশন স্পেসিফিকেশন কাস্টমাইজ করতে পারেন। আরও তথ্যের জন্য AnimationSpec
দেখুন।
একটি ট্রানজিশনের মাধ্যমে একসাথে একাধিক প্রোপার্টি অ্যানিমেট করুন
Transition
এক বা একাধিক অ্যানিমেশনকে তার সন্তান হিসেবে পরিচালনা করে এবং একাধিক রাজ্যের মধ্যে একই সাথে চালায়।
স্টেটগুলি যেকোনো ডেটা টাইপ হতে পারে। অনেক ক্ষেত্রে, আপনি টাইপের নিরাপত্তা যাচাই করতে একটি কাস্টম enum
টাইপ ব্যবহার করতে পারেন, যেমন এই উদাহরণে:
enum class BoxState { Collapsed, Expanded }
updateTransition
Transition
একটি উদাহরণ তৈরি করে এবং মনে রাখে এবং এর অবস্থা আপডেট করে।
var currentState by remember { mutableStateOf(BoxState.Collapsed) } val transition = updateTransition(currentState, label = "box state")
এরপর আপনি এই ট্রানজিশনে চাইল্ড অ্যানিমেশন সংজ্ঞায়িত করতে animate*
এক্সটেনশন ফাংশনগুলির একটি ব্যবহার করতে পারেন। প্রতিটি অবস্থার জন্য লক্ষ্য মান নির্দিষ্ট করুন। এই animate*
ফাংশনগুলি একটি অ্যানিমেশন মান প্রদান করে যা অ্যানিমেশনের সময় প্রতিটি ফ্রেমে আপডেট করা হয় যখন ট্রানজিশন অবস্থা updateTransition
দিয়ে আপডেট করা হয়।
val rect by transition.animateRect(label = "rectangle") { state -> when (state) { BoxState.Collapsed -> Rect(0f, 0f, 100f, 100f) BoxState.Expanded -> Rect(100f, 100f, 300f, 300f) } } val borderWidth by transition.animateDp(label = "border width") { state -> when (state) { BoxState.Collapsed -> 1.dp BoxState.Expanded -> 0.dp } }
ঐচ্ছিকভাবে, আপনি প্রতিটি ট্রানজিশন অবস্থা পরিবর্তনের সংমিশ্রণের জন্য একটি ভিন্ন AnimationSpec
নির্দিষ্ট করতে একটি transitionSpec
প্যারামিটার পাস করতে পারেন। আরও তথ্যের জন্য AnimationSpec
দেখুন।
val color by transition.animateColor( transitionSpec = { when { BoxState.Expanded isTransitioningTo BoxState.Collapsed -> spring(stiffness = 50f) else -> tween(durationMillis = 500) } }, label = "color" ) { state -> when (state) { BoxState.Collapsed -> MaterialTheme.colorScheme.primary BoxState.Expanded -> MaterialTheme.colorScheme.background } }
একবার একটি ট্রানজিশন টার্গেট অবস্থায় পৌঁছে গেলে, Transition.currentState
এবং Transition.targetState
একই রকম হয়। ট্রানজিশন শেষ হয়েছে কিনা তা জানার জন্য আপনি এটিকে একটি সংকেত হিসেবে ব্যবহার করতে পারেন।
কখনও কখনও, আপনি প্রথম টার্গেট স্টেট থেকে আলাদা একটি প্রাথমিক স্টেট রাখতে চাইতে পারেন। এটি অর্জনের জন্য আপনি MutableTransitionState
সহ updateTransition
ব্যবহার করতে পারেন। উদাহরণস্বরূপ, এটি আপনাকে কোডটি কম্পোজিশনে প্রবেশ করার সাথে সাথে অ্যানিমেশন শুরু করতে দেয়।
// Start in collapsed state and immediately animate to expanded var currentState = remember { MutableTransitionState(BoxState.Collapsed) } currentState.targetState = BoxState.Expanded val transition = rememberTransition(currentState, label = "box state") // ……
একাধিক কম্পোজেবল ফাংশন সম্বলিত আরও জটিল ট্রানজিশনের জন্য, আপনি একটি চাইল্ড ট্রানজিশন তৈরি করতে createChildTransition
ব্যবহার করতে পারেন। এই কৌশলটি একটি জটিল কম্পোজেবলের একাধিক উপ-উপাদানের মধ্যে উদ্বেগগুলি পৃথক করার জন্য কার্যকর। প্যারেন্ট ট্রানজিশন চাইল্ড ট্রানজিশনের সমস্ত অ্যানিমেশন মান সম্পর্কে সচেতন।
enum class DialerState { DialerMinimized, NumberPad } @Composable fun DialerButton(isVisibleTransition: Transition<Boolean>) { // `isVisibleTransition` spares the need for the content to know // about other DialerStates. Instead, the content can focus on // animating the state change between visible and not visible. } @Composable fun NumberPad(isVisibleTransition: Transition<Boolean>) { // `isVisibleTransition` spares the need for the content to know // about other DialerStates. Instead, the content can focus on // animating the state change between visible and not visible. } @Composable fun Dialer(dialerState: DialerState) { val transition = updateTransition(dialerState, label = "dialer state") Box { // Creates separate child transitions of Boolean type for NumberPad // and DialerButton for any content animation between visible and // not visible NumberPad( transition.createChildTransition { it == DialerState.NumberPad } ) DialerButton( transition.createChildTransition { it == DialerState.DialerMinimized } ) } }
AnimatedVisibility
এবং AnimatedContent
সাথে ট্রানজিশন ব্যবহার করুন
Transition
এর এক্সটেনশন ফাংশন হিসেবে AnimatedVisibility
এবং AnimatedContent
পাওয়া যায়। Transition.AnimatedVisibility
and Transition.AnimatedContent
এর জন্য targetState
Transition
থেকে উদ্ভূত হয় এবং Transition
এর targetState
পরিবর্তন হলে প্রয়োজন অনুসারে enter, exit, এবং sizeTransform
অ্যানিমেশন ট্রিগার করে। এই এক্সটেনশন ফাংশনগুলি আপনাকে সমস্ত enter, exit, এবং sizeTransform
অ্যানিমেশনগুলিকে Transition
এ উত্তোলন করতে দেয় যা অন্যথায় AnimatedVisibility
/ AnimatedContent
এর অভ্যন্তরীণ হবে। এই এক্সটেনশন ফাংশনগুলির সাহায্যে, আপনি বাইরে থেকে AnimatedVisibility
/ AnimatedContent
এর অবস্থার পরিবর্তন পর্যবেক্ষণ করতে পারেন। একটি বুলিয়ান visible
প্যারামিটারের পরিবর্তে, AnimatedVisibility
এর এই সংস্করণটি একটি ল্যাম্বডা নেয় যা প্যারেন্ট ট্রানজিশনের টার্গেট অবস্থাকে একটি বুলিয়ানে রূপান্তর করে।
বিস্তারিত জানার জন্য AnimatedVisibility
এবং AnimatedContent
দেখুন।
var selected by remember { mutableStateOf(false) } // Animates changes when `selected` is changed. val transition = updateTransition(selected, label = "selected state") val borderColor by transition.animateColor(label = "border color") { isSelected -> if (isSelected) Color.Magenta else Color.White } val elevation by transition.animateDp(label = "elevation") { isSelected -> if (isSelected) 10.dp else 2.dp } Surface( onClick = { selected = !selected }, shape = RoundedCornerShape(8.dp), border = BorderStroke(2.dp, borderColor), shadowElevation = elevation ) { Column( modifier = Modifier .fillMaxWidth() .padding(16.dp) ) { Text(text = "Hello, world!") // AnimatedVisibility as a part of the transition. transition.AnimatedVisibility( visible = { targetSelected -> targetSelected }, enter = expandVertically(), exit = shrinkVertically() ) { Text(text = "It is fine today.") } // AnimatedContent as a part of the transition. transition.AnimatedContent { targetState -> if (targetState) { Text(text = "Selected") } else { Icon(imageVector = Icons.Default.Phone, contentDescription = "Phone") } } } }
একটি ট্রানজিশনকে ক্যাপসুলেট করুন এবং এটিকে পুনরায় ব্যবহারযোগ্য করুন
সহজ ব্যবহারের ক্ষেত্রে, আপনার UI-এর মতো একই কম্পোজেবলে ট্রানজিশন অ্যানিমেশন সংজ্ঞায়িত করা একটি বৈধ বিকল্প। তবে, অনেকগুলি অ্যানিমেটেড মান সহ একটি জটিল উপাদানের উপর কাজ করার সময়, আপনি অ্যানিমেশন বাস্তবায়নকে কম্পোজেবল UI থেকে আলাদা করতে চাইতে পারেন।
আপনি এমন একটি ক্লাস তৈরি করে এটি করতে পারেন যেখানে সমস্ত অ্যানিমেশন মান থাকবে এবং একটি update
ফাংশন তৈরি করে যা সেই ক্লাসের একটি উদাহরণ প্রদান করবে। আপনি ট্রানজিশন বাস্তবায়নকে নতুন পৃথক ফাংশনে এক্সট্র্যাক্ট করতে পারেন। অ্যানিমেশন লজিককে কেন্দ্রীভূত করার বা জটিল অ্যানিমেশনগুলিকে পুনরায় ব্যবহারযোগ্য করার প্রয়োজন হলে এই প্যাটার্নটি কার্যকর।
enum class BoxState { Collapsed, Expanded } @Composable fun AnimatingBox(boxState: BoxState) { val transitionData = updateTransitionData(boxState) // UI tree Box( modifier = Modifier .background(transitionData.color) .size(transitionData.size) ) } // Holds the animation values. private class TransitionData( color: State<Color>, size: State<Dp> ) { val color by color val size by size } // Create a Transition and return its animation values. @Composable private fun updateTransitionData(boxState: BoxState): TransitionData { val transition = updateTransition(boxState, label = "box state") val color = transition.animateColor(label = "color") { state -> when (state) { BoxState.Collapsed -> Color.Gray BoxState.Expanded -> Color.Red } } val size = transition.animateDp(label = "size") { state -> when (state) { BoxState.Collapsed -> 64.dp BoxState.Expanded -> 128.dp } } return remember(transition) { TransitionData(color, size) } }
rememberInfiniteTransition
দিয়ে একটি অসীম পুনরাবৃত্তিমূলক অ্যানিমেশন তৈরি করুন
InfiniteTransition
Transition
মতো এক বা একাধিক চাইল্ড অ্যানিমেশন থাকে, কিন্তু কম্পোজিশনে প্রবেশ করার সাথে সাথেই অ্যানিমেশনগুলি চলতে শুরু করে এবং অপসারণ না করা পর্যন্ত থামে না। আপনি rememberInfiniteTransition
দিয়ে InfiniteTransition
এর একটি ইনস্ট্যান্স তৈরি করতে পারেন, এবং animateColor
, animatedFloat
, অথবা animatedValue
দিয়ে চাইল্ড অ্যানিমেশন যোগ করতে পারেন। অ্যানিমেশনের স্পেসিফিকেশন নির্দিষ্ট করার জন্য আপনাকে একটি infiniteRepeatable
ও নির্দিষ্ট করতে হবে।
val infiniteTransition = rememberInfiniteTransition(label = "infinite") val color by infiniteTransition.animateColor( initialValue = Color.Red, targetValue = Color.Green, animationSpec = infiniteRepeatable( animation = tween(1000, easing = LinearEasing), repeatMode = RepeatMode.Reverse ), label = "color" ) Box( Modifier .fillMaxSize() .background(color) )
নিম্ন-স্তরের অ্যানিমেশন API গুলি
পূর্ববর্তী বিভাগে উল্লিখিত সমস্ত উচ্চ-স্তরের অ্যানিমেশন API গুলি নিম্ন-স্তরের অ্যানিমেশন API গুলির উপর ভিত্তি করে তৈরি।
animate*AsState
ফাংশনগুলি হল সহজবোধ্য API যা তাৎক্ষণিক মান পরিবর্তনকে অ্যানিমেশন মান হিসেবে রেন্ডার করে। এই কার্যকারিতাটি Animatable
দ্বারা সমর্থিত, যা একটি একক মান অ্যানিমেট করার জন্য একটি কোরোটিন-ভিত্তিক API।
updateTransition
একটি ট্রানজিশন অবজেক্ট তৈরি করে যা একাধিক অ্যানিমেটিং মান পরিচালনা করতে পারে এবং যখন কোনও অবস্থা পরিবর্তন হয় তখন সেগুলি চালাতে পারে। rememberInfiniteTransition
অনুরূপ, কিন্তু এটি একটি অসীম ট্রানজিশন তৈরি করে যা অনির্দিষ্টকালের জন্য চলতে থাকা একাধিক অ্যানিমেশন পরিচালনা করতে পারে। এই সমস্ত API গুলি Animatable
ছাড়া কম্পোজেবল, যার অর্থ আপনি কম্পোজিশনের বাইরে এই অ্যানিমেশনগুলি তৈরি করতে পারেন।
এই সমস্ত API গুলি আরও মৌলিক Animation
API এর উপর ভিত্তি করে তৈরি। যদিও বেশিরভাগ অ্যাপ Animation
সাথে সরাসরি ইন্টারঅ্যাক্ট করে না, আপনি উচ্চ-স্তরের API গুলির মাধ্যমে এর কিছু কাস্টমাইজেশন ক্ষমতা অ্যাক্সেস করতে পারেন। AnimationVector
এবং AnimationSpec
সম্পর্কে আরও তথ্যের জন্য Customize animations দেখুন।
Animatable
: কোরোটিন-ভিত্তিক একক মান অ্যানিমেশন
Animatable
হল একটি ভ্যালু হোল্ডার যা animateTo
ব্যবহার করে পরিবর্তনের সাথে সাথে মানটিকে অ্যানিমেট করতে পারে। এটি animate*AsState
বাস্তবায়নের জন্য API। এটি ধারাবাহিক ধারাবাহিকতা এবং পারস্পরিক এক্সক্লুসিভনেস নিশ্চিত করে, যার অর্থ হল মান পরিবর্তন সর্বদা অবিচ্ছিন্ন থাকে এবং Compose যেকোনো চলমান অ্যানিমেশন বাতিল করে।
Animatable
এর অনেক বৈশিষ্ট্য, যার মধ্যে animateTo
ও রয়েছে, হল suspend ফাংশন। এর অর্থ হল আপনাকে এগুলিকে একটি উপযুক্ত coroutine স্কোপে মুড়িয়ে রাখতে হবে। উদাহরণস্বরূপ, আপনি LaunchedEffect
composable ব্যবহার করে নির্দিষ্ট কী মানের সময়কালের জন্য একটি স্কোপ তৈরি করতে পারেন।
// Start out gray and animate to green/red based on `ok` val color = remember { Animatable(Color.Gray) } LaunchedEffect(ok) { color.animateTo(if (ok) Color.Green else Color.Red) } Box( Modifier .fillMaxSize() .background(color.value) )
পূর্ববর্তী উদাহরণে, আপনি Color.Gray
এর প্রাথমিক মান সহ Animatable
এর একটি উদাহরণ তৈরি এবং মনে রাখবেন। boolean flag ok
এর মানের উপর নির্ভর করে, রঙটি Color.Green
অথবা Color.Red
এ অ্যানিমেট হয়। boolean মানের পরবর্তী যেকোনো পরিবর্তন অন্য রঙে একটি অ্যানিমেশন শুরু করে। যদি কোনও অ্যানিমেশন চলমান থাকে যখন মান পরিবর্তন হয়, তাহলে Compose অ্যানিমেশনটি বাতিল করে দেয় এবং নতুন অ্যানিমেশনটি বর্তমান স্ন্যাপশট মান থেকে বর্তমান বেগের সাথে শুরু হয়।
এই Animatable
API হল পূর্ববর্তী বিভাগে উল্লিখিত animate*AsState
জন্য অন্তর্নিহিত বাস্তবায়ন। Animatable
সরাসরি ব্যবহার করলে বিভিন্ন উপায়ে আরও সূক্ষ্ম নিয়ন্ত্রণ পাওয়া যায়:
- প্রথমত,
Animatable
একটি প্রাথমিক মান তার প্রথম লক্ষ্য মানের থেকে আলাদা হতে পারে। উদাহরণস্বরূপ, পূর্ববর্তী কোড উদাহরণে প্রথমে একটি ধূসর বাক্স দেখানো হয়েছে, যা তাৎক্ষণিকভাবে সবুজ বা লাল রঙে অ্যানিমেট হয়ে যায়। - দ্বিতীয়ত,
Animatable
কন্টেন্ট মানের উপর আরও বেশি ক্রিয়াকলাপ প্রদান করে, বিশেষ করেsnapTo
এবংanimateDecay
।-
snapTo
বর্তমান মানটিকে তাৎক্ষণিকভাবে লক্ষ্য মানের সাথে সেট করে। এটি তখন কার্যকর যখন অ্যানিমেশনটি সত্যের একমাত্র উৎস নয় এবং অন্যান্য অবস্থার সাথে সিঙ্ক্রোনাইজ করতে হবে, যেমন টাচ ইভেন্ট। -
animateDecay
একটি অ্যানিমেশন শুরু করে যা প্রদত্ত বেগ থেকে ধীর হয়ে যায়। এটি ফ্লিং আচরণ বাস্তবায়নের জন্য কার্যকর।
-
আরও তথ্যের জন্য অঙ্গভঙ্গি এবং অ্যানিমেশন দেখুন।
ডিফল্টরূপে, Animatable
Float
এবং Color
সমর্থন করে, তবে আপনি একটি TwoWayConverter
প্রদান করে যেকোনো ডেটা টাইপ ব্যবহার করতে পারেন। আরও তথ্যের জন্য AnimationVector দেখুন।
আপনি একটি AnimationSpec
প্রদান করে অ্যানিমেশন স্পেসিফিকেশন কাস্টমাইজ করতে পারেন। আরও তথ্যের জন্য AnimationSpec
দেখুন।
Animation
: ম্যানুয়ালি নিয়ন্ত্রিত অ্যানিমেশন
Animation
হল সর্বনিম্ন স্তরের অ্যানিমেশন API। আমরা এখন পর্যন্ত যেসব অ্যানিমেশন দেখেছি তার বেশিরভাগই Animation
উপর ভিত্তি করে তৈরি। Animation
দুটি উপপ্রকার রয়েছে: TargetBasedAnimation
এবং DecayAnimation
।
অ্যানিমেশনের সময় ম্যানুয়ালি নিয়ন্ত্রণ করার জন্য শুধুমাত্র Animation
ব্যবহার করুন। Animation
স্টেটলেস, এবং এতে জীবনচক্রের কোনও ধারণা নেই। এটি উচ্চ-স্তরের API-এর জন্য একটি অ্যানিমেশন গণনা ইঞ্জিন হিসেবে কাজ করে।
TargetBasedAnimation
অন্যান্য API গুলি বেশিরভাগ ব্যবহারের ক্ষেত্রে প্রযোজ্য, কিন্তু TargetBasedAnimation
ব্যবহার করে আপনি সরাসরি অ্যানিমেশনের প্লে টাইম নিয়ন্ত্রণ করতে পারবেন। নিম্নলিখিত উদাহরণে, আপনি withFrameNanos
দ্বারা প্রদত্ত ফ্রেম টাইমের উপর ভিত্তি করে TargetAnimation
এর প্লে টাইম ম্যানুয়ালি নিয়ন্ত্রণ করতে পারবেন।
val anim = remember { TargetBasedAnimation( animationSpec = tween(200), typeConverter = Float.VectorConverter, initialValue = 200f, targetValue = 1000f ) } var playTime by remember { mutableLongStateOf(0L) } LaunchedEffect(anim) { val startTime = withFrameNanos { it } do { playTime = withFrameNanos { it } - startTime val animationValue = anim.getValueFromNanos(playTime) } while (someCustomCondition()) }
DecayAnimation
TargetBasedAnimation
বিপরীতে, DecayAnimation
এর জন্য targetValue
প্রদানের প্রয়োজন হয় না। পরিবর্তে, এটি initialVelocity
এবং initialValue
এবং সরবরাহকৃত DecayAnimationSpec
দ্বারা নির্ধারিত শুরুর শর্তের উপর ভিত্তি করে তার targetValue
গণনা করে।
ক্ষয় অ্যানিমেশনগুলি প্রায়শই ফ্লিং জেসচারের পরে ব্যবহার করা হয় যাতে উপাদানগুলিকে থামানো যায়। অ্যানিমেশন বেগ initialVelocityVector
দ্বারা সেট করা মান থেকে শুরু হয় এবং সময়ের সাথে সাথে ধীর হয়ে যায়।
আপনার জন্য প্রস্তাবিত
- দ্রষ্টব্য: জাভাস্ক্রিপ্ট বন্ধ থাকলে লিঙ্ক টেক্সট প্রদর্শিত হয়।
- অ্যানিমেশন কাস্টমাইজ করুন
- কম্পোজে অ্যানিমেশন
- অ্যানিমেশন মডিফায়ার এবং কম্পোজেবল