শুধু অ্যানিমেশন নিয়ে কাজ করার তুলনায় টাচ ইভেন্ট ও অ্যানিমেশন নিয়ে কাজ করার সময় আমাদের অনেক বিষয় বিবেচনা করতে হয়। প্রথমত, টাচ ইভেন্ট শুরু হলে, আমাদের হয়ত চলমান অ্যানিমেশন বন্ধ করতে হবে, কারণ ব্যবহারকারীর ইন্টার্যাকশনকে সবচেয়ে বেশি অগ্রাধিকার দেওয়া উচিত।
নিচের উদাহরণে, আমরা একটি Animatable ব্যবহার করে বৃত্তাকার কম্পোনেন্টের অফসেট
পজিশন বোঝাই। টাচ ইভেন্ট
pointerInput মডিফায়ারের মাধ্যমে প্রসেস করা হয়। আমরা নতুন ট্যাপ ইভেন্ট শনাক্ত করলে, ট্যাপ পজিশনে
অফসেট ভ্যালু অ্যানিমেট করতে animateTo কল
করি। অ্যানিমেশন চলাকালীনও ট্যাপ ইভেন্ট হতে পারে
এবং সেই ক্ষেত্রে, animateTo চলমান অ্যানিমেশনকে বাধা দেয় এবং
বাধা দেওয়া অ্যানিমেশনের ভেলোসিটি বজায় রেখে নতুন টার্গেট পজিশনে অ্যানিমেশন
শুরু করে।
@Composable fun Gesture() { val offset = remember { Animatable(Offset(0f, 0f), Offset.VectorConverter) } Box( modifier = Modifier .fillMaxSize() .pointerInput(Unit) { coroutineScope { while (true) { // Detect a tap event and obtain its position. awaitPointerEventScope { val position = awaitFirstDown().position launch { // Animate to the tap position. offset.animateTo(position) } } } } } ) { Circle(modifier = Modifier.offset { offset.value.toIntOffset() }) } } private fun Offset.toIntOffset() = IntOffset(x.roundToInt(), y.roundToInt())
আরেকটি সাধারণ প্যাটার্ন হল, আমাদের অ্যানিমেশন ভ্যালুগুলিকে টাচ ইভেন্ট থেকে আসা ভ্যালুগুলির
সাথে সিঙ্ক্রোনাইজ করতে হয়, যেমন ড্র্যাগ করা। নিচের উদাহরণে, আমরা দেখতে পাচ্ছি যে "বাতিল করতে সোয়াইপ করুন" Modifier হিসেবে প্রয়োগ করা হয়েছে (এর পরিবর্তে
SwipeToDismiss কম্পোজ করার উপযুক্ত আইটেম ব্যবহার করা হয়নি)।
এলিমেন্টের হরাইজন্টাল অফসেটকে Animatable হিসেবে দেখানো হয়। এই API-তে জেসচার অ্যানিমেশনে কাজে লাগে এমন
বৈশিষ্ট্য আছে। টাচ ইভেন্ট এবং
অ্যানিমেশনের মাধ্যমে এর ভ্যালু পরিবর্তন করা যেতে পারে। আমরা টাচ ডাউন ইভেন্ট পেলে, Animatable-কে
stop মেথডের মাধ্যমে বন্ধ করে দিই যাতে কোনও চলমান অ্যানিমেশন ইন্টারসেপ্ট করা যায়।
ড্র্যাগ ইভেন্টের সময়, টাচ ইভেন্ট থেকে গণনা করা ভ্যালু দিয়ে Animatable ভ্যালু আপডেট করতে আমরা snapTo ব্যবহার করি। ফ্লিংয়ের জন্য, কম্পোজ
VelocityTracker ড্র্যাগ ইভেন্ট রেকর্ড করতে এবং ভেলোসিটি গণনা করতে প্রদান করে। ফ্লিং অ্যানিমেশনের জন্য ভেলোসিটি সরাসরি animateDecay-এ
ফিড করা যেতে পারে। অফসেট ভ্যালুকে
আগের অবস্থানে ফিরিয়ে আনতে চাইলে, আমরা 0f-এর টার্গেট অফসেট
ভ্যালু animateTo মেথডের মাধ্যমে নির্দিষ্ট করি।
fun Modifier.swipeToDismiss( onDismissed: () -> Unit ): Modifier = composed { val offsetX = remember { Animatable(0f) } pointerInput(Unit) { // Used to calculate fling decay. val decay = splineBasedDecay<Float>(this) // Use suspend functions for touch events and the Animatable. coroutineScope { while (true) { val velocityTracker = VelocityTracker() // Stop any ongoing animation. offsetX.stop() awaitPointerEventScope { // Detect a touch down event. val pointerId = awaitFirstDown().id horizontalDrag(pointerId) { change -> // Update the animation value with touch events. launch { offsetX.snapTo( offsetX.value + change.positionChange().x ) } velocityTracker.addPosition( change.uptimeMillis, change.position ) } } // No longer receiving touch events. Prepare the animation. val velocity = velocityTracker.calculateVelocity().x val targetOffsetX = decay.calculateTargetValue( offsetX.value, velocity ) // The animation stops when it reaches the bounds. offsetX.updateBounds( lowerBound = -size.width.toFloat(), upperBound = size.width.toFloat() ) launch { if (targetOffsetX.absoluteValue <= size.width) { // Not enough velocity; Slide back. offsetX.animateTo( targetValue = 0f, initialVelocity = velocity ) } else { // The element was swiped away. offsetX.animateDecay(velocity, decay) onDismissed() } } } } } .offset { IntOffset(offsetX.value.roundToInt(), 0) } }
আপনার জন্য সাজেস্ট করা হয়েছে
- মনে রাখবেন: জাভাস্ক্রিপ্ট বন্ধ থাকলে লিঙ্ক টেক্সট দেখানো হয়
- ভ্যালু-ভিত্তিক অ্যানিমেশন
- টেনে আনা, সোয়াইপ করা ও ফ্লিং করা
- জেসচার সম্পর্কে বুঝুন