Flutter / واجهات شاملة وأدلة الأهداف / الدرس 14
الحركة وأعمار الموارد
اختر الحركة الضمنية أو الصريحة بحسب التحكم المطلوب واجعل الحركة تابعة للمعنى ودورة الحياة.
في هذه الصفحة
أهداف الدرس
- حرّك تغير حالة ذا معنى
- فضّل الحركة الضمنية عندما تكفي القيم النهائية
- امتلك وحدات التحكم الصريحة داخل State
حرّك تغير حالة ذا معنى
ينبغي أن تساعد الحركة المستخدم على فهم الاستمرار أو السببية أو تغير الأهمية. ليست بديلا عن تغير الحالة؛ فلا بد أن يوضح مؤشر الحفظ النجاح دون الاعتماد على الحركة أو اللون وحدهما. ابدأ بالحالتين الأصلية والنهائية وحدّد هل يسمح بالمقاطعة أو العكس. قد يبقى التأثير الزخرفي ضمنيا بينما يحتاج تسلسل تقوده إيماءة إلى تحكم صريح بالتقدم. أدرج تفضيلات الحركة في عقد التصميم ووفّر مسارا بحركة مخففة عند المناسبة. اختبر التفاعل السريع المتكرر، فالحركة لا تتلقى دائما تفعيلة منفردة مثالية.
فضّل الحركة الضمنية عندما تكفي القيم النهائية
تدير عناصر الحركة الضمنية آليتها بينما تقدم أنت القيمة النهائية الجديدة. تفيد في حجم أو محاذاة أو زخرفة تنتقل بعد تغير الحالة. يغير المقتطف الأول ارتفاع الحاوية بحسب علم expanded موجود. ولا يخزن ارتفاعا متحركا ثانيا في حالة التطبيق. يستوفي الإطار العرض نحو الهدف الحالي. وإذا تغير العلم ثانية أثناء الانتقال، فاختبر بقاء الحركة مفهومة وعدم اختفاء المحتوى من الإتاحة مع بقائه متفاعلا بصريا.
Widget animatedPreview(bool expanded) => AnimatedContainer(
duration: const Duration(milliseconds: 180),
curve: Curves.easeInOut,
height: expanded ? 160 : 80,
color: Colors.teal,
child: const Center(child: Text('Preview')),
);
Changing expanded animates the bounded height between 80 and 160 logical pixels.
المدة اختيار تصميم توضيحي لا توصية عامة. يجب أن يسمح الأب بالحجمين النهائيين.
امتلك وحدات التحكم الصريحة داخل State
تكشف AnimationController تقدما يمكن بدءه أو عكسه أو إيقافه أو تنسيقه مع قيم أخرى. تحتاج إلى مزوّد ticker ومالك تحرير صريح. ينشئ المقتطف الثاني وحدة التحكم في initState ويحررها في dispose. يناسب SingleTickerProviderStateMixin عمر الوحدة الواحدة المعروض، وقد تحتاج ترتيبات أخرى إلى مزوّد موثق مختلف. لا تنشئ وحدة تحكم جديدة مع كل build ولا تبقها حية لمجرد أن رد نداء ما زال يشير إليها. يجب أن تنهي مغادرة العنصر الموارد التي تملكها State.
class _PulseState extends State<Pulse> with SingleTickerProviderStateMixin {
late final AnimationController controller;
@override void initState() {
super.initState();
controller = AnimationController(vsync: this,
duration: const Duration(milliseconds: 300));
}
@override void dispose() { controller.dispose(); super.dispose(); }
@override Widget build(BuildContext context) => FadeTransition(
opacity: controller, child: const Text('Ready'));
}
The initial controller value is 0; explicit progress changes drive opacity.
Pulse هو StatefulWidget المحيط. يقرر التفاعل الحقيقي متى يستدعي forward أو reverse؛ ولا يبدأ المقتطف الحركة تلقائيا.
افهم الحالة المرئية وحالة التفاعل
لا يعني انعدام العتامة تلقائيا أن الشجرة لا تستقبل اللمس أو التركيز. عند إخفاء لوحة تفاعلية نسّق الظهور مع سياسة التفاعل والدلالات، ولا تفترض أن التلاشي يعطّلها. وبالمقابل قد يؤدي حذف الشجرة فورا إلى خسارة المسودة المحلية بينما يتوقع المنتج إخفاء مؤقتا. اختر هل تبقى اللوحة في الشجرة وتحفظ الحالة وتتلقى الإدخال وتظهر دلاليا في كل مرحلة. هذه قرارات مستقلة ينبغي اختبارها معا عند الفتح والإغلاق ومقاطعة الحركة.
أبعد العمل المكلف عن ردود كل إطار
قد تعيد الحركة البناء أو الرسم كثيرا. انقل الأشجار الثابتة إلى وسيط child مستقر حيث تدعمه الواجهة، وتجنب فك حمولات كبيرة أو الوصول للبيانات داخل باني الحركة. قِس هل الاختناق في عمل Dart أم التخطيط أم الرسم قبل إضافة حدود. قد تكلف طبقة خارج الشاشة غير لازمة أو إعادة رسم واسعة حتى مع بساطة وحدة الحركة. استخدم دليلا من نمط profile على هدف ممثل، فقد يخفي عبء debug وعتاد سطح المكتب تجربة الجهاز المقصود.
اختبر التقدم والمقاطعة والإزالة
يمكن لاختبار عنصر مضبوط ضخ الإطار الأول ثم تقديم مدة مختارة وفحص عرض وسيط ثم إكمال الانتقال. أضف عكسا قبل الاكتمال وأزل المالك أثناء النشاط لاختبار التنظيف. لا تعتمد على pumpAndSettle لحركة تتكرر عمدا، إذ قد لا تستقر. تحقق من بقاء المهمة قابلة للاستخدام مع تعطيل الحركة أو تخفيفها بحسب السياسة. يثبت اختبار الإطارات سلوك الشجرة المختبرة، بينما يظل انتظام الإطارات والتفاعل المساعد الفعلي بحاجة إلى ملاحظة الهدف.
الأخطاء الشائعة وإصلاحها
يبقى ticker نشطا بعد مغادرة الشاشة
- لماذا يحدث؟
- لم تحرر State المالكة وحدة التحكم.
- كيف تصلحه؟
- حرّر وحدة التحكم المملوكة قبل إكمال تحرير State.
- كيف تتجنب تكراره؟
- أزل العنصر أثناء حركة نشطة في اختبار.
يقبل تحكم غير مرئي الإدخال
- لماذا يحدث؟
- اعتُبرت العتامة بوابة للتفاعل.
- كيف تصلحه؟
- نسّق اختبار اللمس والتركيز والدلالات مع حالة الإخفاء.
- كيف تتجنب تكراره؟
- اختبر انتقالات الإغلاق بلوحة المفاتيح واللمس.
تتسبب حركة متكررة في انتهاء مهلة الاختبار
- لماذا يحدث؟
- ينتظر الاختبار حالة لا تستقر.
- كيف تصلحه؟
- قدّم إطارات مضبوطة وأكّد فترة محددة.
- كيف تتجنب تكراره؟
- اختر أدوات التوقيت من عقد الحركة.
اختبر فهمك
1. متى تبرر وحدة تحكم صريحة بدلا من AnimatedContainer؟
اعرض الحل المشروح
عندما يحتاج التفاعل تقدما مباشرا أو تسلسلا منسقا أو حركة تقودها إيماءة أو بدءا وعكسا مقصودين. إذا كان المهم الحجم النهائي الجديد فقط فعنصر ضمني أبسط غالبا. اختر من السلوك المطلوب وتعقيد العمر لا من افتراض تفوق الشيفرة الصريحة.
2. ما الذي يُفحص حين تحتوي لوحة مخفية حقل نص؟
اعرض الحل المشروح
قرّر هل تبقى المسودة وأين ينتقل التركيز وهل تتلقى العناصر المخفية الإدخال وهل تكشفها الدلالات. تحقق من هذه الاختيارات أثناء الانتقال وبعده؛ فالعتامة وحدها لا تجيب عنها.
أهم ما تعلمته
- حرّك تغير حالة ذا معنى
- اختبر التقدم والمقاطعة والإزالة