أنواع لوحة المفاتيح وإجراءات إدخال النص
أنواع لوحة المفاتيح وإجراءات إدخال النص
عندما تضع حقل TextField في نموذج Flutter، فإن خاصيتين تحسّنان تجربة المستخدم بشكل ملحوظ: keyboardType وtextInputAction. الأولى تتحكم في نوع لوحة المفاتيح التي يعرضها نظام التشغيل، والثانية تتحكم في وظيفة زر الإجراء في الزاوية السفلية اليمنى من لوحة المفاتيح. معاً يُقلّلان الاحتكاك بإظهار المفاتيح المناسبة في اللحظة المناسبة.
فهم keyboardType
تقبل خاصية keyboardType ثابتاً من نوع TextInputType. تمرر Flutter هذه الإشارة إلى النظام الأساسي (Android/iOS)، الذي يعرض بعدها أنسب متغير للوحة المفاتيح. أكثر القيم استخداماً هي:
- TextInputType.text — لوحة مفاتيح QWERTY الافتراضية للنص العام
- TextInputType.emailAddress — QWERTY مع ظهور بارز للرمزين
@و. - TextInputType.number — لوحة أرقام رقمية (0–9)؛ بدون فاصلة عشرية أو إشارة افتراضياً
- TextInputType.phone — لوحة اتصال هاتفية تتضمن
+و*و# - TextInputType.multiline — لوحة مفاتيح عادية مع مفتاح سطر جديد بدلاً من مفتاح إرسال/تم
- TextInputType.url — يضيف اختصارات
/و.comعلى iOS - TextInputType.visiblePassword — لوحة نصية مع إخفاء شريط الاقتراح
- TextInputType.numberWithOptions(decimal: true, signed: true) — لوحة رقمية تقبل القيم العشرية والسالبة
keyboardType هي تلميح وليست قيداً صارماً. قد يتجاهله النظام في بعض الإعدادات. أضف دائماً inputFormatters إلى جانب keyboardType إذا كنت بحاجة إلى تحقق صارم (مثل منع الحروف غير الرقمية).فهم textInputAction
تقبل خاصية textInputAction ثابتاً من نوع TextInputAction. تُغيّر تسمية أو أيقونة زر الإجراء الأساسي في لوحة المفاتيح:
- TextInputAction.next — يعرض سهماً للأمام أو "التالي"؛ ينقل التركيز إلى الحقل التالي عادةً
- TextInputAction.done — يعرض "تم" أو علامة صح؛ يُغلق لوحة المفاتيح
- TextInputAction.search — يعرض أيقونة عدسة مكبّرة؛ مناسب لحقول البحث
- TextInputAction.go — يعرض "انتقال"؛ يُستخدم لحقول URL أو التنقل
- TextInputAction.send — يعرض "إرسال"؛ مثالي لحقول تأليف الرسائل
- TextInputAction.newline — يُدرج سطراً جديداً؛ يُستخدم مع الحقول متعددة الأسطر
textInputAction: TextInputAction.next مع رد الاتصال onFieldSubmitted أو onSubmitted واستدعِ FocusScope.of(context).nextFocus() لإنشاء تدفق انتقال سلس بين حقول النموذج المتعددة.مثال برمجي 1 — نموذج تسجيل بأنواع متعددة من لوحات المفاتيح
يوضح النموذج التالي أربعة أنواع مختلفة من لوحات المفاتيح لشاشة تسجيل المستخدم:
class RegistrationForm extends StatefulWidget {
const RegistrationForm({super.key});
@override
State<RegistrationForm> createState() => _RegistrationFormState();
}
class _RegistrationFormState extends State<RegistrationForm> {
final _formKey = GlobalKey<FormState>();
final _nameFocus = FocusNode();
final _emailFocus = FocusNode();
final _phoneFocus = FocusNode();
final _ageFocus = FocusNode();
@override
void dispose() {
_nameFocus.dispose();
_emailFocus.dispose();
_phoneFocus.dispose();
_ageFocus.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Form(
key: _formKey,
child: Column(
children: [
// لوحة مفاتيح نصية افتراضية؛ الإجراء ينتقل إلى حقل البريد الإلكتروني
TextFormField(
focusNode: _nameFocus,
keyboardType: TextInputType.text,
textInputAction: TextInputAction.next,
decoration: const InputDecoration(labelText: 'الاسم الكامل'),
onFieldSubmitted: (_) =>
FocusScope.of(context).requestFocus(_emailFocus),
),
// لوحة بريد إلكتروني (@، . سهلة الوصول)؛ الإجراء ينتقل للهاتف
TextFormField(
focusNode: _emailFocus,
keyboardType: TextInputType.emailAddress,
textInputAction: TextInputAction.next,
decoration: const InputDecoration(labelText: 'البريد الإلكتروني'),
onFieldSubmitted: (_) =>
FocusScope.of(context).requestFocus(_phoneFocus),
),
// لوحة اتصال هاتفية (+، *، #)؛ الإجراء ينتقل لحقل العمر
TextFormField(
focusNode: _phoneFocus,
keyboardType: TextInputType.phone,
textInputAction: TextInputAction.next,
decoration: const InputDecoration(labelText: 'رقم الهاتف'),
onFieldSubmitted: (_) =>
FocusScope.of(context).requestFocus(_ageFocus),
),
// لوحة أرقام فقط؛ تم يُغلق لوحة المفاتيح
TextFormField(
focusNode: _ageFocus,
keyboardType: TextInputType.number,
textInputAction: TextInputAction.done,
decoration: const InputDecoration(labelText: 'العمر'),
onFieldSubmitted: (_) => _submitForm(),
),
ElevatedButton(
onPressed: _submitForm,
child: const Text('تسجيل'),
),
],
),
);
}
void _submitForm() {
if (_formKey.currentState!.validate()) {
_formKey.currentState!.save();
// معالجة التسجيل…
}
}
}
مثال برمجي 2 — حقل البحث وملاحظات متعددة الأسطر
فيما يلي نمطان متخصصان للحقول ستستخدمهما بشكل متكرر في التطبيقات الحقيقية:
// --- حقل البحث ---
// textInputAction.search يعرض أيقونة عدسة مكبّرة على زر الإجراء.
// اربط رد الاتصال لتشغيل منطق البحث فوراً.
TextField(
keyboardType: TextInputType.text,
textInputAction: TextInputAction.search,
decoration: const InputDecoration(
prefixIcon: Icon(Icons.search),
hintText: 'ابحث عن منتجات…',
border: OutlineInputBorder(),
),
onSubmitted: (query) => _runSearch(query),
),
// --- حقل ملاحظات متعدد الأسطر ---
// keyboardType.multiline يجب اقترانه بـ maxLines != 1 حتى يتوسع الحقل.
// textInputAction.newline يبقي مفتاح Enter كسطر جديد حقيقي
// بدلاً من إغلاق لوحة المفاتيح.
TextField(
keyboardType: TextInputType.multiline,
textInputAction: TextInputAction.newline,
maxLines: 5,
decoration: const InputDecoration(
labelText: 'ملاحظات',
alignLabelWithHint: true,
border: OutlineInputBorder(),
),
),
// --- حقل سعر عشري ---
// numberWithOptions(decimal: true) يعرض فاصل الأرقام العشرية
// على لوحة الأرقام، الذي يغيب عن TextInputType.number البسيط في بعض الأجهزة.
TextField(
keyboardType: const TextInputType.numberWithOptions(decimal: true),
textInputAction: TextInputAction.done,
decoration: const InputDecoration(
labelText: 'السعر',
prefixText: 'ر.س ',
),
),
keyboardType: TextInputType.multiline دون ضبط maxLines على قيمة تختلف عن 1 (أو null لعدد غير محدود). إذا بقي maxLines على قيمته الافتراضية 1، لن يتوسع الحقل وسيفقد مفتاح السطر الجديد أثره، مما يُربك المستخدمين.الأرقام العشرية والموقّعة
استخدم TextInputType.numberWithOptions(decimal: true, signed: true) عندما يجب أن يقبل حقلك الأسعار والقياسات أو درجات الحرارة. يضيف خيار decimal مفتاح الفاصلة العشرية، ويضيف خيار signed مفتاح الإشارة السالبة — وكلاهما غائب عن لوحة الأرقام العادية في كثير من الأجهزة.
فروقات المنصات التي يجب مراعاتها
- على iOS، يعرض
TextInputType.numberلوحة أرقام بسيطة؛ يظهر مفتاح الفاصلة العشرية فقط عند ضبطdecimal: true. - على Android، تتضمن لوحة الأرقام عادةً مفتاح الفاصلة العشرية، لكن السلوك يتفاوت بحسب لوحة مفاتيح الشركة المصنّعة.
- قد يُترجم نص تم أو التالي من قِبل نظام التشغيل؛ اعتمد على الأيقونة أو الموضع لا على النص في تصميم واجهتك.
ملخص
يُعدّ ضبط keyboardType وtextInputAction من أسرع التحسينات في تجربة مستخدم النماذج. استخدم لوحة البريد الإلكتروني للبريد الإلكتروني، ولوحة الأرقام للأعمار والأسعار، ولوحة الهاتف لأرقام الهاتف، ومتعدد الأسطر للنصوص الحرة. اقرن TextInputAction.next مع ربط عقد التركيز حتى يتنقل المستخدمون بين الحقول دون لمس الشاشة، واستخدم TextInputAction.done أو TextInputAction.search كإجراء نهائي للإرسال أو الإغلاق.