TextField

ما هو TextField؟

TextField هو الويدجت الأساسي في Flutter لالتقاط النص من المستخدم.

يعتمد داخليًا على EditableText. مناسب لحالات الإدخال البسيطة أو عندما لا تحتاج تحقق/فالديشن (validation) متقدم داخل Form.
إذا كنت تريد تحقق (validator) أو استخدامه داخل Form مع FormState فاستعمل TextFormField

(وهو غلاف يضيف خاصية validator).

الفرق بسرعة: TextField vs TextFormField
  • TextField: مناسب عندما تريد مجرد إدخال نص وتشغيل callbacks مثل onChanged أو onSubmitted.
  • TextFormField: يضيف إمكانية الربط مع Form واستخدام validator و onSaved، مفيد في نماذج (forms).
خصائص TextField المهمة (قائمة شاملة مع الشرح والقيم الشائعة)

الخصائص مقسَّمة بحسب نوعها:

إدارة النص، مظهر/ديكور، سلوك لوحة المفاتيح، تحكم في المؤشر/التحديد، أحداث/callbacks، قيود/تنسيقات، وأخرى مفيدة.

إدارة النص:
  • controller: TextEditingController?
    كائن للتحكم بقاعدة النص، قراءة/كتابة النص برمجياً، الاستماع للتغيرات. تأكد من عمل dispose() له إذا أنشأته داخل StatefulWidget.
  • focusNode: FocusNode?
    للتحكم بالتركيز (focus) برمجياً، الاستماع لأحداث التركيز.
  • readOnly: bool (default: false)
    لعرض النص فقط (لا تحرير) لكن يسمح بتحديد/نسخ النص عادة.
  • enabled: bool? (default: true)
    تعطيل الحقل بالكامل (مقترن بالمظهر في InputDecoration).
مظهر وديكور
  • decoration: InputDecoration
    كل شيء عن الشكل — labelText, hintText, helperText, errorText, prefixIcon, suffixIcon, border, filled, fillColor, contentPadding, floatingLabelBehavior، إلخ.
  • style: TextStyle?
    ستايل النص داخل الحقل.
  • textAlign: TextAlign (default: TextAlign.start)
    محاذاة النص (start, center, right, left).
  • textAlignVertical: TextAlignVertical?
    لمحاذاة رأسية (مفيد لمربعات متعددة الأسطر أو عندما يوجد أيقونات).
  • cursorColor: Color?, cursorWidth: double?, cursorRadius: Radius?, showCursor: bool?
    تحكم في مظهر المؤشر (cursor).
سلوك لوحة المفاتيح / نوع الإدخال
  • keyboardType: TextInputType?
    مثل TextInputType.text, TextInputType.emailAddress, TextInputType.number, TextInputType.multiline, TextInputType.phone, TextInputType.datetime
  • textInputAction: TextInputAction?
    زر الإدخال في الكيبورد (مثلاً TextInputAction.next, done, go, search).
  • textCapitalization: TextCapitalization
    none, characters, words, sentences.
  • keyboardAppearance: Brightness?
    لون لوحة المفاتيح (iOS عادة).
إخفاء النص (كلمات السر) وسمات متعلقة
  • obscureText: bool (default: false)
    إذا كان true يُظهر نقاط بدل الحروف (كلمة مرور).
  • obscuringCharacter: String (default: "•")
    الحرف المستخدم للإخفاء.
طول/أسطر/تمدد
  • maxLines: int? (default: 1)
    أقصى عدد أسطر؛ اجعله null للسماح بعدد لا نهائي.
  • minLines: int?
    أدنى عدد أسطر.
  • expands: bool (default: false)
    عندما true مع maxLines = null وminLines = null، يتمدد الحقل ليملأ المساحة المتاحة.
  • maxLength: int?
    الحد الأقصى لعدد الحروف (يظهر عدّاد في الـ InputDecoration إلا إذا عطَّلت ذلك).
القيود / تنسيقات الإدخال
  • inputFormatters: List<TextInputFormatter>?
    للتحكم في النص المدخل (مثلاً FilteringTextInputFormatter.digitsOnly, أو تنسيقات مخصصة).
  • keyboardType مع inputFormatters مفيد للحقول الرقمية أو التواريخ.
التحديد ونسخ/لصق
  • enableInteractiveSelection: bool? (default: true)
    تمكين تحديد/نسخ/لصق.
  • selectionControls (متقدم) — لتخصيص أزرار النسخ/لصق (نادراً تستخدم).
أحداث / callbacks
  • onChanged: ValueChanged<String>?
    يستدعى مع كل تغيير للنص.
  • onEditingComplete: VoidCallback?
    استدعاء عند اكتمال التحرير (عادة عند الضغط على زر الإدخال).
  • onSubmitted: ValueChanged<String>?
    عند الضغط على زر الإدخال (مثلاً done).
  • onTap: GestureTapCallback?
    عند النقر على الحقل.
سلوك ذكي وتصحيحات
  • autocorrect: bool? (default: true)
    تمكين التصحيح التلقائي.
  • enableSuggestions: bool?
    تمكين اقتراحات لوحة المفاتيح.
  • autofillHints: Iterable<String>?
    لمساعدة نظام الملء التلقائي (مثلاً AutofillHints.email, username, password).
سلوك التمرير و المسافات
  • scrollPadding: EdgeInsets (default: EdgeInsets.all(20))
    المساحة التي يضيفها النظام عند ظهور الكيبورد لمنع تغطية الحقل.
  • dragStartBehavior (Behavior for gestures) — نادر الاستخدام.
الوصول (accessibility) وstate restoration
  • restorationId — إن أردت دعم استعادة حالة (state restoration).
  • enableIMEPersonalizedLearning — خاص بالـ IME (أحدث).

ملاحظة: بعض الخصائص مرتبطة بتنفيذ داخلي أو قد تختلف أسماءها عبر إصدارات Flutter — ما فوق هي القائمة العملية الأكثر استخدامًا.

خصائص InputDecoration الشائعة (لأنها جزء أساسي من مظهر TextField)
  • labelText, labelStyle
  • hintText, hintStyle
  • helperText
  • errorText (عند وجود خطأ)
  • icon (أيقونة خارج الحقل على اليسار)
  • prefixIcon, suffixIcon (أيقونات داخل الحقل على الطرفين)
  • prefix, suffix (يمكن أن تكون Widgets أوسع من أيقونة)
  • border, enabledBorder, focusedBorder, errorBorder, focusedErrorBorder (أنماط OutlineInputBorder, UnderlineInputBorder…)
  • filled: bool, fillColor
  • isDense (يجعل الحقل أقل ارتفاعًا)
  • contentPadding (مسافة داخل الحقل)
  • counterText أو counter (لتحكم بعداد الأحرف)
  • floatingLabelBehavior (always, auto, never) — سلوك عنوان العلامة.
نصائح مهمة وعملية
  • إذا أنشأت TextEditingController أو FocusNode داخل StatefulWidget، دُمِّرهما في dispose().
  • استخدم TextFormField داخل Form عندما تحتاج validator و onSaved.
  • لتغيير مظهر كل الحقول في التطبيق: استخدم ThemeData.inputDecorationTheme.
  • استخدم inputFormatters لمنع أحرف غير مرغوب فيها (أقوى من onChanged لأنه يطبق قبل إدخال النص).
  • لحقل كلمة المرور: استخدم obscureText مع زر في suffixIcon لتبديل الإخفاء.
  • للأرقام الحساسة للأداء: استخدم keyboardType: TextInputType.number + FilteringTextInputFormatter.digitsOnly.
  • لتسهيل الوصول: تأكد من labelText واضح وsemanticsLabel إن لزم.
    border: OutlineInputBorder(),
    focusedBorder: OutlineInputBorder(
      borderSide: BorderSide(color: Colors.red),
      borderRadius: BorderRadius.circular(50)
    ),
    enabledBorder: OutlineInputBorder(
      borderSide: BorderSide(color: Colors.green),
      borderRadius: BorderRadius.circular(50)
    )
PHP
أمثلة عملية (شفرة Dart)
1) حقل نص بسيط مع controller و decoration
// داخل StatefulWidget
final TextEditingController _controller = TextEditingController();

@override
void dispose() {
  _controller.dispose();
  super.dispose();
}

Widget build(BuildContext context) {
  return TextField(
    controller: _controller,
    decoration: InputDecoration(
      labelText: 'الاسم',
      hintText: 'ادخل اسمك',
      prefixIcon: Icon(Icons.person),
      border: OutlineInputBorder(),
    ),
    textInputAction: TextInputAction.next,
    onChanged: (value) => print('text changed: $value'),
  );
}
PHP
2) حقل كلمة مرور مع زر إظهار/إخفاء
class PasswordField extends StatefulWidget {
  @override
  _PasswordFieldState createState() => _PasswordFieldState();
}

class _PasswordFieldState extends State<PasswordField> {
  final TextEditingController _passwordController = TextEditingController();
  bool _obscure = true;

  @override
  void dispose() {
    _passwordController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return TextField(
      controller: _passwordController,
      obscureText: _obscure,
      obscuringCharacter: '',
      decoration: InputDecoration(
        labelText: 'كلمة المرور',
        prefixIcon: Icon(Icons.lock),
        suffixIcon: IconButton(
          icon: Icon(_obscure ? Icons.visibility : Icons.visibility_off),
          onPressed: () => setState(() => _obscure = !_obscure),
        ),
        border: OutlineInputBorder(),
      ),
      textInputAction: TextInputAction.done,
    );
  }
}
PHP
3) حقل متعدد الأسطر (ملاحظة: استخدم maxLines أو expands)
TextField(
  decoration: InputDecoration(
    labelText: 'ملاحظة',
    alignLabelWithHint: true,
    border: OutlineInputBorder(),
  ),
  keyboardType: TextInputType.multiline,
  minLines: 3,
  maxLines: 6,
)
PHP
4) حقل رقمي مع تنسيق (أرقام فقط) وعداد طول
TextField(
  keyboardType: TextInputType.number,
  inputFormatters: [
    FilteringTextInputFormatter.digitsOnly, // أرقام فقط
    LengthLimitingTextInputFormatter(10),  // حد 10 أرقام
  ],
  decoration: InputDecoration(
    labelText: 'رقم الهاتف',
    prefixText: '+90 ',
    border: OutlineInputBorder(),
    counterText: '', // لإخفاء العداد الافتراضي إن أردت
  ),
)
PHP
5) استخدام داخل Form مع TextFormField (للتوثيق/التحقق)
final _formKey = GlobalKey<FormState>();
final TextEditingController _emailController = TextEditingController();

Form(
  key: _formKey,
  child: Column(
    children: [
      TextFormField(
        controller: _emailController,
        decoration: InputDecoration(labelText: 'البريد الإلكتروني'),
        keyboardType: TextInputType.emailAddress,
        validator: (value) {
          if (value == null || value.isEmpty) return 'مطلوب';
          if (!RegExp(r'^[^@]+@[^@]+\.[^@]+').hasMatch(value)) return 'بريد غير صالح';
          return null;
        },
      ),
      ElevatedButton(
        onPressed: () {
          if (_formKey.currentState!.validate()) {
            // صالح
          }
        },
        child: Text('إرسال'),
      )
    ],
  ),
)
PHP
مرجع سريع للـ TextInputType وTextCapitalization وTextInputAction
  • TextInputType: text, multiline, number, phone, emailAddress, datetime, url, visiblePassword.
  • TextCapitalization: none, characters, words, sentences.
  • TextInputAction: done, go, next, search, send, none, previous, continueAction, إلخ.
أخطاء شائعة وحلولها
  • نسيان dispose() على TextEditingController أو FocusNode → تسريبات ذاكرة.
  • استخدام maxLines: null بدون expands: true أو غير مناسب يؤدي إلى سلوك تمرير غريب.
  • محاولة استخدام validator مع TextField — لا يعمل، استخدم TextFormField.
  • الحقول داخل Row أو قيود أفقية قد تحتاج Expanded ليتصرف الحقل بشكل صحيح.