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

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

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

الميزة

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

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

المزايا التي تعتمد على الولاية

إدارة الحالة

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

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

  • تمت إزالة دالة الاستدعاء onValueChange، ما يمنعك من تقديم سلوكيات غير متزامنة.
  • وتبقى الحالة محفوظة بعد إعادة التركيب والضبط وإنهاء العملية.

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

يستخدم 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. ننصحك باختيار هذا التنفيذ لأنّه يتبع إرشادات Material Design:
  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 متعدّد الأسطر، مع سطرَين قابلَين للتعديل بالإضافة إلى التصنيف

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

إدخال الأنماط باستخدام Brush API

يمكنك استخدام Brush API للحصول على تنسيق أكثر تقدّمًا في TextField. يوضّح القسم التالي كيفية استخدام فرشاة لإضافة منحدر لانهائي ملوّن إلى إدخال 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)
)

استخدام buildAnnotatedString وSpanStyle، بالإضافة إلى linearGradient، لتخصيص جزء من النص فقط
الشكل 1. تأثير متدرّج لقوس قزح في محتوى TextField

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

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

  • initialText: محتوى TextField
  • initialSelection: يشير إلى موضع المؤشر أو الجزء المحدّد حاليًا.

ما يميز TextFieldState عن الأساليب الأخرى، مثل callback 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,
)

TextField يتضمّن النص Username (اسم المستخدم) الذي يظهر داخل حقل النص
الشكل 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()

LaunchedEffect(phoneNumberState) {
    phoneNumberState.edit { // TextFieldBuffer scope
        append("123456789")
    }
}

TextField(
    state = phoneNumberState,
    inputTransformation = InputTransformation { // TextFieldBuffer scope
        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 والمزيد.

    val usernameState = rememberTextFieldState("I love Android")
    // textFieldState.text : I love Android
    // textFieldState.selection: TextRange(14, 14)
    usernameState.edit { insert(14, "!") }
    // textFieldState.text : I love Android!
    // textFieldState.selection: TextRange(15, 15)
    usernameState.edit { replace(7, 14, "Compose") }
    // textFieldState.text : I love Compose!
    // textFieldState.selection: TextRange(15, 15)
    usernameState.edit { append("!!!") }
    // textFieldState.text : I love Compose!!!!
    // textFieldState.selection: TextRange(18, 18)
    usernameState.edit { selectAll() }
    // textFieldState.text : I love Compose!!!!
    // textFieldState.selection: TextRange(0, 18)

  • setTextAndPlaceCursorAtEnd: لمحو النص الحالي واستبداله بالنص المُعطى وضبط المؤشر في النهاية

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

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

    usernameState.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 (!TextUtils.isDigitsOnly(asCharSequence())) {
            revertAllChanges()
        }
    }
}

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

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

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

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

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

تتيح لك OutputTransformation تنسيق إدخال المستخدم قبل عرضه على الشاشة. على عكس 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 ضبط خيارات إعدادات لوحة المفاتيح، مثل TextFieldتنسيق لوحة المفاتيح، أو تفعيل ميزة التصحيح التلقائي إذا كانت لوحة المفاتيح تتيح ذلك. قد لا يكون بالإمكان ضمان بعض الخيارات إذا لم تكن لوحة المفاتيح البرمجية متوافقة مع الخيارات المقدَّمة هنا. في ما يلي قائمة بإعدادات لوحة المفاتيح المتوافقة:

  • capitalization
  • autoCorrect
  • keyboardType
  • imeAction

مراجع إضافية