ما هو 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: TextCapitalizationnone,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,labelStylehintText,hintStylehelperTexterrorText(عند وجود خطأ)icon(أيقونة خارج الحقل على اليسار)prefixIcon,suffixIcon(أيقونات داخل الحقل على الطرفين)prefix,suffix(يمكن أن تكون Widgets أوسع من أيقونة)border,enabledBorder,focusedBorder,errorBorder,focusedErrorBorder(أنماطOutlineInputBorder,UnderlineInputBorder…)filled: bool,fillColorisDense(يجعل الحقل أقل ارتفاعًا)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'),
);
}PHP2) حقل كلمة مرور مع زر إظهار/إخفاء
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,
);
}
}PHP3) حقل متعدد الأسطر (ملاحظة: استخدم maxLines أو expands)
TextField(
decoration: InputDecoration(
labelText: 'ملاحظة',
alignLabelWithHint: true,
border: OutlineInputBorder(),
),
keyboardType: TextInputType.multiline,
minLines: 3,
maxLines: 6,
)PHP4) حقل رقمي مع تنسيق (أرقام فقط) وعداد طول
TextField(
keyboardType: TextInputType.number,
inputFormatters: [
FilteringTextInputFormatter.digitsOnly, // أرقام فقط
LengthLimitingTextInputFormatter(10), // حد 10 أرقام
],
decoration: InputDecoration(
labelText: 'رقم الهاتف',
prefixText: '+90 ',
border: OutlineInputBorder(),
counterText: '', // لإخفاء العداد الافتراضي إن أردت
),
)PHP5) استخدام داخل 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ليتصرف الحقل بشكل صحيح.