ضبط الحقول النصية

تتيح TextField للمستخدمين إدخال النص وتعديله. هناك نوعان من حقول النصوص التي يمكنك استخدامها: حقول النصوص المستندة إلى الحالة وحقول النصوص المستندة إلى القيمة. اختَر نوع المحتوى الذي تريد عرضه:

ننصحك باستخدام حقول نصية مستندة إلى الحالة، لأنّها توفّر طريقة أكثر اكتمالاً وموثوقية لإدارة حالة TextField. يوضّح الجدول التالي الاختلافات بين أنواع حقول النصوص هذه، ويتضمّن المزايا الرئيسية التي توفّرها حقول النصوص المستندة إلى الحالة:

الميزة

الحقول النصية المستندة إلى القيمة

الحقول النصية المستندة إلى الحالة

ميزة حسب الولاية

إدارة الحالة

تعديل حالة حقل النص باستخدام معاودة الاتصال onValueChange أنت المسؤول عن تعديل value في حالتك استنادًا إلى التغييرات التي أبلغت عنها onValueChange.

يستخدم صراحةً عنصر TextFieldState لإدارة حالة إدخال النص (القيمة والتحديد والتركيب). يمكن تذكُّر هذه الحالة ومشاركتها.

  • تمت إزالة onValueChange callback، ما يمنعك من تقديم سلوكيات غير متزامنة.
  • تظل الحالة محفوظة عند إعادة التركيب وتغيير الإعدادات وإيقاف العملية نهائيًا.

التحويل المرئي

يتم استخدام VisualTransformation لتعديل طريقة ظهور النص المعروض. ويتعامل هذا الإجراء عادةً مع تنسيق كلّ من المدخلات والمخرجات في خطوة واحدة.

يستخدم InputTransformation لتعديل إدخال المستخدم قبل حفظه في الحالة، وOutputTransformation لتنسيق محتوى حقل النص بدون تغيير بيانات الحالة الأساسية.

  • لم يعُد عليك تقديم عملية الربط بين النص الأولي الأصلي والنص المحوّل باستخدام OutputTransformation.

حدود الأسطر

يقبل singleLine: Boolean, maxLines: Int وminLines: Int للتحكّم في عدد الأسطر.

يتم استخدام lineLimits: TextFieldLineLimits لضبط الحدّ الأدنى والأقصى لعدد الأسطر التي يمكن أن يشغلها الحقل النصي.

  • تزيل هذه السمة الغموض عند ضبط حدود الأسطر من خلال توفير المَعلمة lineLimits من النوع TextFieldLineLimits.

حقل نص آمن

لا ينطبق

‫SecureTextField هي دالة قابلة للإنشاء تستند إلى حقول نصية مستندة إلى الحالة لكتابة حقل كلمة المرور.

  • تتيح لك تحسين الأمان في الخلفية، وتتضمّن واجهة مستخدم محدّدة مسبقًا مع textObfuscationMode.

توضّح هذه الصفحة كيفية تنفيذ TextField وتنسيق إدخال TextField وإعداد خيارات TextField الأخرى، مثل خيارات لوحة المفاتيح وتحويل بيانات أدخلها المستخدم بشكل مرئي.

اختيار طريقة تنفيذ TextField

هناك مستويان لتنفيذ TextField:

  1. ‫TextField هو تنفيذ التصميم المتعدد الأبعاد. ننصحك باختيار هذا التنفيذ لأنّه يتّبع إرشادات Material Design:
    • النمط التلقائي هو ملء
    • ‫OutlinedTextField هو إصدار محدّد من الأنماط
  2. تتيح BasicTextField للمستخدمين تعديل النص باستخدام لوحة المفاتيح المادية أو لوحة المفاتيح الافتراضية، ولكنها لا توفّر أي عناصر زخرفية، مثل التلميحات أو العناصر النائبة.

TextField(
    state = rememberTextFieldState(initialText = "Hello"),
    label = { Text("Label") }
)

حقل نص قابل للتعديل يحتوي على الكلمة

OutlinedTextField(
    state = rememberTextFieldState(),
    label = { Text("Label") }
)

حقل نص قابل للتعديل، مع حدود وتصنيف باللون الأرجواني

النمط TextField

تتشارك TextField وBasicTextField العديد من المَعلمات الشائعة للتخصيص. تتوفّر القائمة الكاملة الخاصة بـ TextField في رمز المصدر الخاص بـ TextField. في ما يلي قائمة غير شاملة ببعض المَعلمات المفيدة:

  • textStyle
  • lineLimits

TextField(
    state = rememberTextFieldState("Hello\nWorld\nInvisible"),
    lineLimits = TextFieldLineLimits.MultiLine(maxHeightInLines = 2),
    placeholder = { Text("") },
    textStyle = TextStyle(color = Color.Blue, fontWeight = FontWeight.Bold),
    label = { Text("Enter text") },
    modifier = Modifier.padding(20.dp)
)

حقل نص متعدّد الأسطر، يتضمّن سطرَين قابلَين للتعديل بالإضافة إلى التصنيف

ننصحك باستخدام TextField بدلاً من BasicTextField عندما يتطلّب تصميمك استخدام TextField أو OutlinedTextField من Material. ومع ذلك، يجب استخدام BasicTextField عند إنشاء تصاميم لا تحتاج إلى الزخارف من مواصفات Material Design.

تنسيق الإدخال باستخدام Brush API

يمكنك استخدام Brush API لتطبيق أنماط أكثر تقدّمًا في TextField. يوضّح القسم التالي كيفية استخدام Brush لإضافة تدرّج ألوان إلى إدخال TextField.

لمزيد من المعلومات حول استخدام Brush API لتصميم النص، يُرجى الاطّلاع على تفعيل التصميم المتقدّم باستخدام Brush API.

تنفيذ تدرّجات الألوان باستخدام TextStyle

لتنفيذ تدرّج لوني أثناء الكتابة داخل TextField، اضبط فرشاتك المفضّلة كـ TextStyle لـ TextField. في هذا المثال، نستخدم فرشاة مضمّنة مع linearGradient لعرض تأثير تدرّج ألوان قوس قزح أثناء كتابة النص في TextField.

val brush = remember {
    Brush.linearGradient(
        colors = listOf(Color.Red, Color.Yellow, Color.Green, Color.Blue, Color.Magenta)
    )
}
TextField(
    state = rememberTextFieldState(), textStyle = TextStyle(brush = brush)
)

نص يتم كتابته في حقل نص، مع عرض تأثير تدرّج ألوان قوس قزح
الشكل 1. تأثير تدرّج ألوان الطيف على محتوى TextField

إدارة حالة حقل النص

تستخدم السمة TextField فئة مخصّصة لتخزين الحالة تُسمى TextFieldState من أجل المحتوى والاختيار. تم تصميم TextFieldState ليتم رفعه أينما كان ذلك مناسبًا في بنيتك. هناك سمتان رئيسيتان توفّرهما TextFieldState:

  • initialText: محتوى TextField
  • ‫initialSelection: تشير إلى موضع المؤشر أو موضع التحديد.

ما يميّز TextFieldState عن الطرق الأخرى، مثل معاودة الاتصال onValueChange، هو أنّ TextFieldState يغلف بالكامل تدفق الإدخال بأكمله. ويشمل ذلك استخدام هياكل البيانات الأساسية الصحيحة، وتضمين الفلاتر وأدوات التنسيق، بالإضافة إلى مزامنة جميع التعديلات الواردة من مصادر مختلفة.

يمكنك استخدام TextFieldState() لنقل الحالة إلى أعلى في TextField. لهذا الغرض، ننصحك باستخدام الدالة rememberTextFieldState(). تنشئ rememberTextFieldState() مثيلاً من TextFieldState في الدالة المركّبة، وتتأكّد من تذكُّر عنصر الحالة، وتوفّر وظيفة مدمجة للحفظ والاستعادة:

val usernameState = rememberTextFieldState()
TextField(
    state = usernameState,
    lineLimits = TextFieldLineLimits.SingleLine,
    placeholder = { Text("Enter Username") }
)

يمكن أن يحتوي rememberTextFieldState على مَعلمة فارغة أو قيمة أولية يتم تمريرها لتمثيل قيمة النص عند التهيئة. إذا تم تمرير قيمة مختلفة في عملية إعادة إنشاء لاحقة، لن يتم تعديل قيمة الحالة. لتعديل الحالة بعد إعدادها، استخدِم طرق التعديل في TextFieldState.

TextField(
    state = rememberTextFieldState(initialText = "Username"),
    lineLimits = TextFieldLineLimits.SingleLine,
)

حقل نصي يظهر فيه النص "اسم المستخدم"
الشكل 2. TextField مع "اسم المستخدم" كنص أولي

تعديل النص باستخدام TextFieldBuffer

تعمل TextFieldBuffer كحاوية نصية قابلة للتعديل، وهي تشبه في وظيفتها StringBuilder. ويحتوي على المحتوى النصي ومعلومات حول النص المحدّد.

يصادفك TextFieldBuffer غالبًا كنطاق مستقبِل في دوال مثل TextFieldState.edit أو InputTransformation.transformInput أو OutputTransformation.transformOutput. في هذه الدوال، يمكنك قراءة TextFieldBuffer أو تعديلها حسب الحاجة. بعد ذلك، يتم إما تطبيق هذه التغييرات على TextFieldState أو تمريرها إلى مسار العرض في حالة OutputTransformation.

يمكنك استخدام وظائف التعديل العادية، مثل append أو insert أو replace أو delete، لتعديل محتوى المخزن المؤقت. لتغيير حالة التحديد، يمكنك إما ضبط المتغيّر selection: TextRange مباشرةً أو استخدام دوال مساعدة مثل placeCursorAtEnd أو selectAll. يتم تمثيل عملية الاختيار نفسها بواسطة TextRange، حيث يكون فهرس البداية مشمولاً وفهرس النهاية غير مشمول. يشير TextRange الذي يتضمّن قيمتَي بدء وانتهاء متطابقتَين، مثل (3, 3)، إلى موضع المؤشر بدون تحديد أي أحرف.

val phoneNumberState = rememberTextFieldState("1234567890")

TextField(
    state = phoneNumberState,
    keyboardOptions = KeyboardOptions(
        keyboardType = KeyboardType.Phone
    ),
    inputTransformation = InputTransformation.maxLength(10).then {
        if (!asCharSequence().isDigitsOnly()) {
            revertAllChanges()
        }
    },
    outputTransformation = OutputTransformation {
        if (length > 0) insert(0, "(")
        if (length > 4) insert(4, ")")
        if (length > 8) insert(8, "-")
    }
)

تعديل النص في TextFieldState

هناك عدة طرق تتيح لك تعديل الحالة مباشرةً من خلال متغير الحالة:

  • edit: تتيح لك تعديل محتوى الحالة وتوفّر لك دوال TextFieldBuffer لتتمكّن من استخدام طرق مثل insert وreplace وappend وغيرها.

    // Initial textFieldState text passed in is "I love Android"
    // textFieldState.text : I love Android
    // textFieldState.selection: TextRange(14, 14)
    textFieldState.edit { insert(14, "!") }
    // textFieldState.text : I love Android!
    // textFieldState.selection: TextRange(15, 15)
    textFieldState.edit { replace(7, 14, "Compose") }
    // textFieldState.text : I love Compose!
    // textFieldState.selection: TextRange(15, 15)
    textFieldState.edit { append("!!!") }
    // textFieldState.text : I love Compose!!!!
    // textFieldState.selection: TextRange(18, 18)
    textFieldState.edit { selectAll() }
    // textFieldState.text : I love Compose!!!!
    // textFieldState.selection: TextRange(0, 18)

  • ‫setTextAndPlaceCursorAtEnd: يمحو النص الحالي ويستبدله بالنص المحدّد، ثم يضع المؤشر في النهاية.

    textFieldState.setTextAndPlaceCursorAtEnd("I really love Android")
    // textFieldState.text : I really love Android
    // textFieldState.selection : TextRange(21, 21)

  • clearText: لمحو كل النص

    textFieldState.clearText()
    // textFieldState.text :
    // textFieldState.selection : TextRange(0, 0)

للاطّلاع على دوال TextFieldState الأخرى، يُرجى الرجوع إلى مرجع TextFieldState.

تعديل بيانات أدخلها المستخدم

توضّح الأقسام التالية كيفية تعديل بيانات أدخلها المستخدم. تتيح لك عملية تحويل الإدخال فلترة TextField الإدخال أثناء الكتابة، بينما تعمل عملية تحويل الإخراج على تنسيق بيانات أدخلها المستخدم قبل عرضها على الشاشة.

فلترة بيانات أدخلها المستخدم باستخدام عمليات تحويل الإدخال

يتيح لك تحويل الإدخال فلترة الإدخال من المستخدم. على سبيل المثال، إذا كان TextField يقبل رقم هاتف أمريكيًا، عليك قبول 10 أرقام فقط. يتم حفظ نتائج InputTransformation في TextFieldState.

تتوفّر فلاتر مضمّنة لحالات الاستخدام الشائعة InputTransformation. لفرض حدّ أقصى على طول المكالمة، اتّصِل بالرقم InputTransformation.maxLength():

TextField(
    state = rememberTextFieldState(),
    lineLimits = TextFieldLineLimits.SingleLine,
    inputTransformation = InputTransformation.maxLength(10)
)

عمليات تحويل الإدخال المخصّصة

InputTransformation هي واجهة دالة واحدة. عند تنفيذ InputTransformation المخصّص، عليك إلغاء TextFieldBuffer.transformInput:

class CustomInputTransformation : InputTransformation {
    override fun TextFieldBuffer.transformInput() {
    }
}

بالنسبة إلى رقم الهاتف، أضِف عملية تحويل إدخال مخصّصة لا تسمح إلا بإدخال أرقام في TextField:

class DigitOnlyInputTransformation : InputTransformation {
    override fun TextFieldBuffer.transformInput() {
        if (!asCharSequence().isDigitsOnly()) {
            revertAllChanges()
        }
    }
}

عمليات تحويل إدخال السلسلة

لإضافة فلاتر متعددة على إدخال النص، اربط InputTransformations باستخدام دالة الإضافة then. يتم تنفيذ الفلاتر بالتسلسل. كأفضل ممارسة، طبِّق الفلاتر الأكثر تحديدًا أولاً لتجنُّب عمليات التحويل غير الضرورية على البيانات التي سيتم استبعادها في النهاية.

TextField(
    state = rememberTextFieldState(),
    inputTransformation = InputTransformation.maxLength(6)
        .then(CustomInputTransformation()),
)

بعد إضافة عمليات تحويل الإدخال، يقبل الإدخال TextField 10 أرقام كحد أقصى.

تنسيق الإدخال قبل عرضه

تتيح لك OutputTransformations تنسيق إدخال المستخدم قبل عرضه على الشاشة. على عكس InputTransformation، لا يتم حفظ التنسيق الذي يتم إجراؤه من خلال OutputTransformation في TextFieldState. استنادًا إلى مثال رقم الهاتف السابق، عليك إضافة أقواس وشرطات في المواضع المناسبة:

رقم هاتف أمريكي، منسّق بشكل صحيح باستخدام أقواس وشرطات وفهارس مقابلة
الشكل 3. رقم هاتف أمريكي بالتنسيق المناسب والفهارس المقابلة

هذه هي الطريقة المعدَّلة للتعامل مع VisualTransformation في TextField المستندة إلى القيمة، ويتمثّل الاختلاف الرئيسي في أنّك لست بحاجة إلى احتساب عمليات الربط بين الإزاحات.

‫OutputTransformation هي واجهة طريقة مجرّدة واحدة. لتنفيذ OutputTransformation مخصّص، عليك إلغاء طريقة transformOutput:

class CustomOutputTransformation : OutputTransformation {
    override fun TextFieldBuffer.transformOutput() {
    }
}

لتنسيق رقم هاتف، أضِف قوسًا مفتوحًا في الفهرس 0 وقوسًا مغلقًا في الفهرس 4 وشرطة في الفهرس 8 إلى OutputTransformation:

class PhoneNumberOutputTransformation : OutputTransformation {
    override fun TextFieldBuffer.transformOutput() {
        if (length > 0) insert(0, "(")
        if (length > 4) insert(4, ")")
        if (length > 8) insert(8, "-")
    }
}

بعد ذلك، أضِف OutputTransformation إلى TextField:

TextField(
    state = rememberTextFieldState(),
    outputTransformation = PhoneNumberOutputTransformation()
)

طريقة عمل عمليات التحويل معًا

يوضّح المخطّط البياني التالي عملية الانتقال من إدخال النص إلى تحويله إلى الناتج:

رسم توضيحي يبيّن كيفية خضوع النص المُدخَل لعمليات تحويل قبل أن يصبح نصًا مُخرَجًا
الشكل 4. مخطّط بياني يوضّح كيف يخضع النص المُدخَل لعمليات تحويل قبل أن يصبح نصًا مُخرَجًا
  1. يتم تلقّي الإدخال من مصدر الإدخال.
  2. يتم فلترة الإدخال من خلال InputTransformation، ويتم حفظه في TextFieldState.
  3. يتم تمرير الإدخال من خلال OutputTransformation للتنسيق.
  4. يتم عرض الإدخال في TextField.

ضبط خيارات لوحة المفاتيح

تتيح لك TextField ضبط خيارات إعداد لوحة المفاتيح، مثل تخطيط لوحة المفاتيح، أو تفعيل التصحيح التلقائي إذا كانت لوحة المفاتيح تتيح ذلك. قد لا تتوفّر بعض الخيارات إذا كانت لوحة المفاتيح الافتراضية لا تتوافق مع الخيارات الموضّحة هنا. في ما يلي قائمة خيارات لوحة المفاتيح المتوافقة:

  • capitalization
  • autoCorrect
  • keyboardType
  • imeAction

مراجع إضافية