محاذاة المحور الرئيسي والمحور المتقاطع
فهم المحاور في Flutter
كل Row و Column لديه محوران: المحور الرئيسي والمحور المتقاطع. فهم كيفية عمل هذه المحاور أمر أساسي للتحكم في موضع وتباعد العناصر الفرعية داخل عنصر التخطيط.
- Row: المحور الرئيسي = أفقي (من اليسار لليمين)، المحور المتقاطع = عمودي (من الأعلى للأسفل)
- Column: المحور الرئيسي = عمودي (من الأعلى للأسفل)، المحور المتقاطع = أفقي (من اليسار لليمين)
يوفر Flutter خاصيتين رئيسيتين للتحكم في المحاذاة على هذه المحاور: mainAxisAlignment و crossAxisAlignment.
MainAxisAlignment
تتحكم خاصية mainAxisAlignment في كيفية توزيع العناصر الفرعية على المحور الرئيسي. هناك ست خيارات:
MainAxisAlignment.start
يضع العناصر الفرعية في بداية المحور الرئيسي. هذه هي القيمة الافتراضية.
MainAxisAlignment.start
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Container(width: 60, height: 60, color: Colors.red),
Container(width: 60, height: 60, color: Colors.green),
Container(width: 60, height: 60, color: Colors.blue),
],
)
// النتيجة: [أحمر][أخضر][أزرق].................
MainAxisAlignment.end
يضع العناصر الفرعية في نهاية المحور الرئيسي.
MainAxisAlignment.end
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Container(width: 60, height: 60, color: Colors.red),
Container(width: 60, height: 60, color: Colors.green),
Container(width: 60, height: 60, color: Colors.blue),
],
)
// النتيجة: .................[أحمر][أخضر][أزرق]
MainAxisAlignment.center
يوسّط العناصر الفرعية على المحور الرئيسي.
MainAxisAlignment.center
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Container(width: 60, height: 60, color: Colors.red),
Container(width: 60, height: 60, color: Colors.green),
Container(width: 60, height: 60, color: Colors.blue),
],
)
// النتيجة: ........[أحمر][أخضر][أزرق]........
MainAxisAlignment.spaceBetween
يوزع المساحة الإضافية بالتساوي بين العناصر الفرعية. يلامس العنصر الأول حافة البداية ويلامس العنصر الأخير حافة النهاية.
MainAxisAlignment.spaceBetween
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Container(width: 60, height: 60, color: Colors.red),
Container(width: 60, height: 60, color: Colors.green),
Container(width: 60, height: 60, color: Colors.blue),
],
)
// النتيجة: [أحمر]........[أخضر]........[أزرق]
MainAxisAlignment.spaceAround
يوزع المساحة الإضافية بالتساوي، مع نصف المساحة قبل العنصر الأول وبعد العنصر الأخير.
MainAxisAlignment.spaceAround
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
Container(width: 60, height: 60, color: Colors.red),
Container(width: 60, height: 60, color: Colors.green),
Container(width: 60, height: 60, color: Colors.blue),
],
)
// النتيجة: ..[أحمر]....[أخضر]....[أزرق]..
MainAxisAlignment.spaceEvenly
يوزع المساحة الإضافية بالتساوي، بما في ذلك مساحة متساوية قبل العنصر الأول وبعد العنصر الأخير.
MainAxisAlignment.spaceEvenly
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Container(width: 60, height: 60, color: Colors.red),
Container(width: 60, height: 60, color: Colors.green),
Container(width: 60, height: 60, color: Colors.blue),
],
)
// النتيجة: ...[أحمر]...[أخضر]...[أزرق]...
spaceAround و spaceEvenly دقيق لكنه مهم. مع spaceAround، تباعد الحواف نصف التباعد بين العناصر. مع spaceEvenly، كل الفجوات متطابقة.CrossAxisAlignment
تتحكم خاصية crossAxisAlignment في كيفية وضع العناصر الفرعية على المحور المتقاطع. هناك خمس خيارات:
CrossAxisAlignment.center (الافتراضي)
يوسّط العناصر الفرعية على المحور المتقاطع.
CrossAxisAlignment.center
Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Container(width: 60, height: 40, color: Colors.red),
Container(width: 60, height: 80, color: Colors.green),
Container(width: 60, height: 60, color: Colors.blue),
],
)
CrossAxisAlignment.start
يحاذي العناصر الفرعية عند بداية المحور المتقاطع (أعلى لـ Row، يسار لـ Column).
CrossAxisAlignment.start
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(width: 60, height: 40, color: Colors.red),
Container(width: 60, height: 80, color: Colors.green),
Container(width: 60, height: 60, color: Colors.blue),
],
)
CrossAxisAlignment.end
يحاذي العناصر الفرعية عند نهاية المحور المتقاطع (أسفل لـ Row، يمين لـ Column).
CrossAxisAlignment.end
Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: <Widget>[
Container(width: 60, height: 40, color: Colors.red),
Container(width: 60, height: 80, color: Colors.green),
Container(width: 60, height: 60, color: Colors.blue),
],
)
CrossAxisAlignment.stretch
يمدد العناصر الفرعية لملء المحور المتقاطع بالكامل. هذا مفيد للغاية لجعل كل العناصر بنفس الارتفاع في Row أو بنفس العرض في Column.
CrossAxisAlignment.stretch
SizedBox(
height: 100,
child: Row(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Container(width: 60, color: Colors.red),
Container(width: 60, color: Colors.green),
Container(width: 60, color: Colors.blue),
],
),
)
// كل الحاويات الثلاث أصبحت بارتفاع 100 بكسل
CrossAxisAlignment.stretch، يجب أن يكون للعنصر الأب حجم محدود على المحور المتقاطع. بالنسبة لـ Row، يجب أن يكون للعنصر الأب ارتفاع محدد. بالنسبة لـ Column، يجب أن يكون للعنصر الأب عرض محدد. وإلا لن يتمكن Flutter من تحديد الحجم الذي يجب التمدد إليه.CrossAxisAlignment.baseline
يحاذي العناصر الفرعية على خط الأساس النصي. هذا أساسي عندما يكون لديك نصوص بأحجام مختلفة يجب أن تصطف عند أسفل الحروف. يجب أيضاً تعيين خاصية textBaseline عند استخدام هذه المحاذاة.
CrossAxisAlignment.baseline
Row(
crossAxisAlignment: CrossAxisAlignment.baseline,
textBaseline: TextBaseline.alphabetic,
children: <Widget>[
Text('كبير', style: TextStyle(fontSize: 40)),
Text('متوسط', style: TextStyle(fontSize: 24)),
Text('صغير', style: TextStyle(fontSize: 14)),
],
)
// كل النصوص الثلاثة تتحاذى على خط الأساس
خاصية textBaseline
عند استخدام CrossAxisAlignment.baseline، يجب تحديد أي خط أساس تستخدم:
- TextBaseline.alphabetic -- يحاذي عند أسفل الأحرف الأبجدية (الأكثر شيوعاً للخطوط اللاتينية والعربية والمشابهة).
- TextBaseline.ideographic -- يحاذي عند أسفل الأحرف الإيديوغرافية (يُستخدم للخطوط الصينية واليابانية والكورية).
CrossAxisAlignment.baseline بدون تعيين textBaseline، سيُطلق Flutter خطأ تأكيد أثناء التشغيل. احرص دائماً على إقرانهما معاً.كيف تختلف المحاذاة بين Row و Column
نفس خاصية المحاذاة تتصرف بشكل مختلف حسب ما إذا كنت تستخدمها في Row أو Column لأن المحاور مُتبادلة:
نفس المحاذاة، عنصر مختلف
// في Row: العناصر الفرعية توسّط أفقياً
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [Text('أ'), Text('ب'), Text('ج')],
)
// في Column: العناصر الفرعية توسّط عمودياً
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [Text('أ'), Text('ب'), Text('ج')],
)
// في Row: العناصر الفرعية تمتد عمودياً
Row(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [Container(width: 50, color: Colors.red)],
)
// في Column: العناصر الفرعية تمتد أفقياً
Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [Container(height: 50, color: Colors.red)],
)
مثال عملي: محتوى موسّط
نمط شائع هو توسيط المحتوى أفقياً وعمودياً على الشاشة:
محتوى موسّط بالكامل
Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Icon(Icons.check_circle, size: 80, color: Colors.green),
SizedBox(height: 16),
Text(
'نجاح!',
style: TextStyle(fontSize: 28, fontWeight: FontWeight.bold),
),
SizedBox(height: 8),
Text(
'تم تقديم طلبك بنجاح.',
style: TextStyle(fontSize: 16, color: Colors.grey),
),
],
),
)
مثال عملي: تنقل متساوي التباعد
أشرطة التنقل السفلية غالباً ما تستخدم عناصر متساوية التباعد:
تخطيط شريط التنقل السفلي
Container(
padding: EdgeInsets.symmetric(vertical: 8),
decoration: BoxDecoration(
color: Colors.white,
boxShadow: [BoxShadow(color: Colors.black12, blurRadius: 4)],
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
Column(
mainAxisSize: MainAxisSize.min,
children: [Icon(Icons.home, color: Colors.blue), Text('الرئيسية', style: TextStyle(fontSize: 12))],
),
Column(
mainAxisSize: MainAxisSize.min,
children: [Icon(Icons.search, color: Colors.grey), Text('بحث', style: TextStyle(fontSize: 12))],
),
Column(
mainAxisSize: MainAxisSize.min,
children: [Icon(Icons.favorite, color: Colors.grey), Text('المفضلة', style: TextStyle(fontSize: 12))],
),
Column(
mainAxisSize: MainAxisSize.min,
children: [Icon(Icons.person, color: Colors.grey), Text('الملف', style: TextStyle(fontSize: 12))],
),
],
),
)
مثال عملي: نص محاذى على خط الأساس
عند عرض سعر مع عملة، يجب أن تتحاذى الأرقام ورمز العملة على خط الأساس:
عرض السعر بمحاذاة خط الأساس
Row(
crossAxisAlignment: CrossAxisAlignment.baseline,
textBaseline: TextBaseline.alphabetic,
children: <Widget>[
Text('\$', style: TextStyle(fontSize: 20, color: Colors.grey)),
Text('49', style: TextStyle(fontSize: 48, fontWeight: FontWeight.bold)),
Text('.99', style: TextStyle(fontSize: 20, color: Colors.grey)),
Text('/شهر', style: TextStyle(fontSize: 14, color: Colors.grey)),
],
)
بدون محاذاة خط الأساس، ستكون أحجام النص المختلفة موسّطة عمودياً افتراضياً، مما يخلق مظهراً غير طبيعي. محاذاة خط الأساس تضمن أن كل النص يجلس على نفس الخط البصري.
الملخص
- MainAxisAlignment يتحكم في التوزيع على اتجاه التخطيط: start و end و center و spaceBetween و spaceAround و spaceEvenly.
- CrossAxisAlignment يتحكم في التموضع العمودي على اتجاه التخطيط: start و end و center و stretch و baseline.
- المحاور تتبادل بين Row (محور رئيسي أفقي) و Column (محور رئيسي عمودي).
- استخدم
CrossAxisAlignment.stretchلجعل كل العناصر الفرعية تملأ المحور المتقاطع -- يتطلب عنصراً أباً محدود الأبعاد. - استخدم
CrossAxisAlignment.baselineمعtextBaselineلمحاذاة نصوص بأحجام مختلفة. spaceEvenlyيوزع فجوات متساوية في كل مكان؛spaceAroundيعطي نصف فجوات عند الحواف؛spaceBetweenبدون فجوات عند الحواف.