إتقان التحريك المعقد في فلاتر (Flutter Animations): من البساطة إلى الاحتراف
أهلاً بيك يا صديقي المبرمج. أكيد جالك وقت وأنت شغال على تطبيق فلاتر (Flutter)، العميل أو حتى ذوقك الشخصي طلب "حركة" معينة في الشاشة، حاجة كدة تدي روح للتطبيق وتخليه يبان بريميوم. في البداية، بنبدأ بالأنيميشن البسيط زي AnimatedContainer أو AnimatedOpacity، وبنحس إن الدنيا تمام. لكن أول ما المشروع يكبر وتطلب منك حركة "مخصصة" (Custom Animation) فيها تسلسل، تحكم دقيق في التوقيت، أو ربط الحركة بحدث معين، هنا بتبدأ الحيرة والوجع.
في المقال ده، هنشيل الغموض عن الانتقال من الـ Implicit Animations (الأنيميشن الضمني) إلى القوة الحقيقية المتمثلة في AnimationController، عشان تقدر تبني أي حركة تخطر على بالك.
Table of contents [Show]
ليه بنحتاج نخرج بره الـ Implicit Animations؟
الأنيميشن الضمني زي AnimatedOpacity سهل جداً؛ إنت بتقوله اتغير من قيمة 0 لـ 1، وهو بياخد المهمة على عاتقه. لكن المشكلة بتبدأ لما تحب تعمل حركة مركبة، زي إن عنصر يتحرك "يطلع وينزل" وتغير لونه في نفس الوقت، أو إنك توقف الحركة في لحظة معينة، أو حتى تعكسها. هنا الـ Explicit Animations هي حلك الوحيد.
مكونات السحر: الـ AnimationController والـ Tween
عشان تعمل أنيميشن "بإيدك" (Explicit)، إنت محتاج تلات حاجات أساسية:
- AnimationController: ده "الميسترو" أو المدير اللي بيتحكم في وقت الحركة (تبدأ إمتى، تخلص إمتى، وتتكرر كام مرة).
- Tween: ده اللي بيحدد النطاق (Range) بتاع الحركة. يعني من قيمة 0.0 إلى 1.0 أو من لون أحمر لأزرق.
- Animation: ده المتغير اللي بيحمل القيمة الحالية للحركة في كل فريم.
مثال عملي: بناء حركة مخصصة
خلينا نشوف كود بسيط بيعمل دوران (Rotation) لعنصر، وده اللي هيوضحلك الفكرة:
class MyCustomAnimation extends StatefulWidget {
@override
_MyCustomAnimationState createState() => _MyCustomAnimationState();
}
class _MyCustomAnimationState extends State with SingleTickerProviderStateMixin {
late AnimationController _controller;
late Animation _animation;
@override
void initState() {
super.initState();
_controller = AnimationController(
duration: const Duration(seconds: 2),
vsync: this,
)..repeat(reverse: true);
_animation = Tween(begin: 0, end: 2 * 3.14).animate(_controller);
}
@override
Widget build(BuildContext context) {
return RotationTransition(
turns: _animation,
child: FlutterLogo(size: 100),
);
}
}
التعامل مع المنحنيات (Curves) لإضافة "لمسة طبيعية"
الأنيميشن اللي سرعته ثابتة بيبان "روبوتك" ومش طبيعي. عشان تخلي الحركة بروفيشنال، لازم تستخدم الـ CurvedAnimation. الميزة هنا إنك بتقدر تدي الحركة طابع تسارعي (Ease In/Out) يخلي المستخدم يحس إن العنصر له وزن وحركة حقيقية في الواقع.
نصيحة من أخ لمطور فلاتر
يا صديقي، نصيحتي ليك إن الأنيميشن مش بس "تزيين"، الأنيميشن جزء من تجربة المستخدم (User Experience - UX). حاول دايماً متكترش في الأنيميشن عشان متضايقش المستخدم، وخليه دايماً بيخدم غرض وظيفي (مثلاً يوضح إن في حاجة اتغيرت). اتدرب كتير على AnimationController، وابدأ شوف مكتبات زي Lottie لو الأنيميشن معقد جداً، لكن خلّيك متمكن من الأدوات الأساسية الأول، لأن دي اللي بتميز المبرمج الشاطر عن الهاوي.
استمر في التجربة، واكسر الكود وجربه تاني، فلاتر فيها بحر من الإمكانيات اللي مستني تكتشفها!