আমরা যখন একা অ্যানিমেশনের সাথে কাজ করি তার তুলনায় আমরা স্পর্শ ইভেন্ট এবং অ্যানিমেশনগুলির সাথে কাজ করার সময় আমাদের বেশ কয়েকটি বিষয় বিবেচনা করতে হবে। প্রথমত, ব্যবহারকারীর মিথস্ক্রিয়াকে সর্বোচ্চ অগ্রাধিকার দেওয়া উচিত বলে স্পর্শ ইভেন্টগুলি শুরু হলে আমাদের একটি চলমান অ্যানিমেশনকে বাধা দিতে হতে পারে।
নীচের উদাহরণে, আমরা একটি বৃত্তের উপাদানের অফসেট অবস্থান উপস্থাপন করতে একটি 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-এর একটি বৈশিষ্ট্য রয়েছে। স্পর্শ ইভেন্টের পাশাপাশি অ্যানিমেশন দ্বারা এর মান পরিবর্তন করা যেতে পারে। যখন আমরা একটি টাচ ডাউন ইভেন্ট পাই, তখন আমরা stop
পদ্ধতিতে Animatable
বন্ধ করি যাতে যেকোন চলমান অ্যানিমেশন আটকে যায়।
একটি ড্র্যাগ ইভেন্টের সময়, আমরা স্পর্শ ইভেন্ট থেকে গণনা করা মানের সাথে Animatable
মান আপডেট করতে snapTo
ব্যবহার করি। ফ্লিং-এর জন্য, কম্পোজ ড্র্যাগ ইভেন্ট রেকর্ড করতে এবং বেগ গণনা করতে VelocityTracker
প্রদান করে। ফ্লিং অ্যানিমেশনের জন্য বেগ সরাসরি animateDecay
খাওয়ানো যেতে পারে। যখন আমরা অফসেট মানটিকে আসল অবস্থানে স্লাইড করতে চাই, তখন আমরা animateTo
পদ্ধতির সাথে 0f
এর টার্গেট অফসেট মান নির্দিষ্ট করি।
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) } }
আপনার জন্য প্রস্তাবিত
- দ্রষ্টব্য: জাভাস্ক্রিপ্ট বন্ধ থাকলে লিঙ্ক টেক্সট প্রদর্শিত হয়
- মান-ভিত্তিক অ্যানিমেশন
- টেনে আনুন, সোয়াইপ করুন এবং ফ্লিং করুন৷
- ইশারা বুঝুন