ElevatedButton

ما هو ElevatedButton؟

زر Material “مرفوع” بظل خفيف، مناسب للأفعال الأساسية (Primary Action). هو البديل الحديث لـ RaisedButton (الموقوف). سلوكه يتغيّر حسب الحالة (عادي، Hover، Focus، Pressed، Disabled).

البُنى (Constructors)
  • ElevatedButton (القياسي):
ElevatedButton(
  onPressed: () {},
  onLongPress: () {},
  child: Text('اضغط'),
)
Dart

ElevatedButton.icon (مع أيقونة ونص):

ElevatedButton.icon(
  onPressed: () {},
  icon: Icon(Icons.send),
  label: Text('إرسال'),
)
Dart

تعطيل الزر: اجعل onPressed: null

أهم الخصائص المباشرة
الخاصيةالوصف
onPressed / onLongPressدوال الاستجابة للنقر والضغط المطوّل
child / icon + labelمحتوى الزر
styleتخصيص المظهر عبر ButtonStyle
autofocus, focusNode, clipBehaviorوصول لوحة المفاتيح والقص
التخصيص السريع: styleFrom

أسهل طريقة لتخصيص سريع (ينتج ButtonStyle جاهز):

ElevatedButton(
  onPressed: () {},
  style: ElevatedButton.styleFrom(
    backgroundColor: Colors.blue,     // لون الخلفية
    foregroundColor: Colors.white,    // لون النص/الأيقونة
    elevation: 3,                     // الظل
    shadowColor: Colors.black54,
    padding: EdgeInsets.symmetric(horizontal: 20, vertical: 14),
    minimumSize: Size(120, 48),       // أصغر مقاس
    fixedSize: Size.fromHeight(48),   // مقاس ثابت (اختياري)
    shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
    side: BorderSide(color: Colors.blueGrey), // حدود
  ),
  child: Text('زر مخصص'),
)
Dart

ملاحظة (M3): أحيانًا يظهر تأثير Surface Tint الافتراضي من الثيم. إن لم ترغب به عدّله عبر الثيم أو ButtonStyle (انظر أدناه).

التخصيص الاحترافي: ButtonStyle + MaterialStateProperty

لجعل المظهر يتغيّر حسب الحالة (hover/pressed/disabled…):

ElevatedButton(
  onPressed: () {},
  style: ButtonStyle(
    backgroundColor: MaterialStateProperty.resolveWith<Color?>((states) {
      if (states.contains(MaterialState.disabled)) return Colors.grey.shade400;
      if (states.contains(MaterialState.pressed))  return Colors.blue.shade700;
      if (states.contains(MaterialState.hovered))  return Colors.blue.shade600;
      return Colors.blue; // عادي
    }),
    foregroundColor: MaterialStateProperty.all(Colors.white),
    overlayColor: MaterialStateProperty.resolveWith<Color?>((states) {
      if (states.contains(MaterialState.pressed)) return Colors.white.withOpacity(0.12);
      if (states.contains(MaterialState.hovered)) return Colors.white.withOpacity(0.06);
      return null; // الافتراضي
    }),
    elevation: MaterialStateProperty.resolveWith<double>((states) {
      if (states.contains(MaterialState.disabled)) return 0;
      if (states.contains(MaterialState.pressed))  return 8;
      if (states.contains(MaterialState.hovered))  return 4;
      return 2;
    }),
    padding: MaterialStateProperty.all(const EdgeInsets.symmetric(horizontal: 20, vertical: 14)),
    shape: MaterialStateProperty.all(
      RoundedRectangleBorder(borderRadius: BorderRadius.circular(14)),
    ),
    minimumSize: MaterialStateProperty.all(const Size(120, 48)),
    // يمكن أيضًا: foregroundColor, shadowColor, surfaceTintColor, side, textStyle, alignment ...
  ),
  child: const Text('زر بحالات متعددة'),
)
Dart
أهم حقول ButtonStyle المفيدة
  • textStyle: خط النص.
  • backgroundColor, foregroundColor: ألوان الخلفية والنص/الأيقونات.
  • overlayColor: لون طبقة التفاعل (ضغط/هوفر).
  • shadowColor, elevation: لون الظل وارتفاعه.
  • surfaceTintColor (في Material 3): تينت سطح الزر.
  • padding, minimumSize, fixedSize, maximumSize.
  • shape, side: الشكل والحدود.
  • animationDuration, enableFeedback, alignment, visualDensity, tapTargetSize.

قاعدة ذهبية: استخدم resolveWith عندما تريد سلوكًا متغيرًا حسب الحالة.

أمثلة جاهزة مهمة
1) زر بعرض الشاشة (Block Button)
  • الطريقة 1 (مباشرة): dartCopyEditSizedBox( width: double.infinity, child: ElevatedButton( onPressed: () {}, child: Text('متابعة'), ), )
  • الطريقة 2 (من خلال الـ style): dartCopyEditElevatedButton( onPressed: () {}, style: ElevatedButton.styleFrom(minimumSize: const Size.fromHeight(48)), child: const Text('متابعة'), )
2) زر مع أيقونة ونص
ElevatedButton.icon(
  onPressed: () {},
  icon: const Icon(Icons.save),
  label: const Text('حفظ'),
  style: ElevatedButton.styleFrom(padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 12)),
)
Dart
3) زر تحميل (حالة انتظار)
class SaveButton extends StatefulWidget {
  const SaveButton({super.key});
  @override
  State<SaveButton> createState() => _SaveButtonState();
}

class _SaveButtonState extends State<SaveButton> {
  bool loading = false;

  @override
  Widget build(BuildContext context) {
    return ElevatedButton(
      onPressed: loading ? null : () async {
        setState(() => loading = true);
        await Future.delayed(const Duration(seconds: 2));
        setState(() => loading = false);
      },
      style: ElevatedButton.styleFrom(minimumSize: const Size(140, 48)),
      child: loading
        ? const SizedBox(
            width: 22, height: 22,
            child: CircularProgressIndicator(strokeWidth: 2),
          )
        : const Text('حفظ'),
    );
  }
}
Dart
4) زر بحواف كابسول وحدود
ElevatedButton(
  onPressed: () {},
  style: ElevatedButton.styleFrom(
    shape: const StadiumBorder(),
    side: const BorderSide(color: Colors.indigo),
  ),
  child: const Text('Capsule'),
)
Dart
5) جعل الزر شفافًا فوق خلفية متدرجة (حيلة)

لا يوجد Gradient مباشر للخلفية؛ استخدم حاوية بالخلفية، واجعل الزر شفاف الظل/الخلفية:

Container(
  decoration: const BoxDecoration(
    gradient: LinearGradient(colors: [Colors.purple, Colors.blue]),
    borderRadius: BorderRadius.all(Radius.circular(14)),
  ),
  child: ElevatedButton(
    onPressed: () {},
    style: ElevatedButton.styleFrom(
      backgroundColor: Colors.transparent,
      shadowColor: Colors.transparent,
      shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(14)),
      minimumSize: const Size.fromHeight(48),
    ),
    child: const Text('زر متدرّج'),
  ),
)
Dart
6) استخدامه داخل Row مع توزيع المساحة
Row(
  children: [
    Expanded(
      child: ElevatedButton(onPressed: () {}, child: const Text('يسار')),
    ),
    const SizedBox(width: 8),
    Expanded(
      child: ElevatedButton(onPressed: () {}, child: const Text('يمين')),
    ),
  ],
)
Dart
التيمـة (Theme) — توحيد مظهر الأزرار

اضبط شكل جميع أزرار التطبيق من مكان واحد:

MaterialApp(
  theme: ThemeData(
    elevatedButtonTheme: ElevatedButtonThemeData(
      style: ElevatedButton.styleFrom(
        minimumSize: const Size(120, 48),
        shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
        textStyle: const TextStyle(fontWeight: FontWeight.w600),
      ),
    ),
    // في Material 3 يمكن التحكم بـ colorScheme + surfaceTintColor
    // useMaterial3: true,
  ),
  home: const MyHomePage(),
);
Dart

لتغيير الألوان حسب ColorScheme (الموصى به مع Material 3)، اعتمد على colorScheme.primary وonPrimary بدل الألوان الصريحة.

أفضل الممارسات
  • (حديث) فضّل ElevatedButton/TextButton/OutlinedButton على الأزرار القديمة مثل RaisedButton وFlatButton.
  • استخدم styleFrom للتخصيص السريع، وButtonStyle + MaterialStateProperty للحالات المعقدة.
  • لإشارة التعطيل، اجعل onPressed: null — ستطبَّق ألوان وتعطيل مناسب تلقائيًا.
  • للأزرار داخل Column مع عناصر أخرى، استخدم SizedBox أو Expanded لتحديد الارتفاع/التمدد وتجنّب أخطاء القياس.
  • عند الحاجة لتلميح (Tooltip) على سطح المكتب/الويب، لف الزر بـ Tooltip: dartCopyEditTooltip(message: 'حفظ', child: ElevatedButton(onPressed: () {}, child: Text('حفظ')))
  • للأداء والوضوح، استخدم const حيثما أمكن في child.
مقارنة سريعة (متى أستخدم ماذا؟)
  • ElevatedButton: الفعل الأساسي (Primary) أو حيث يلزم تباين قوي/ظل.
  • TextButton: أفعال ثانوية بلا حدود/ظل (روابط، “تعلّم المزيد”).
  • OutlinedButton: أفعال ثانوية بحدّ واضح بدون تعبئة.