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

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

اختيار عملية تنفيذ TextField

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

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

@Composable
fun SimpleFilledTextFieldSample() {
    var text by remember { mutableStateOf("Hello") }

    TextField(
        value = text,
        onValueChange = { text = it },
        label = { Text("Label") }
    )
}

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

@Composable
fun SimpleOutlinedTextFieldSample() {
    var text by remember { mutableStateOf("") }

    OutlinedTextField(
        value = text,
        onValueChange = { text = it },
        label = { Text("Label") }
    )
}

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

النمط TextField

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

  • singleLine
  • maxLines
  • textStyle

@Composable
fun StyledTextField() {
    var value by remember { mutableStateOf("Hello\nWorld\nInvisible") }

    TextField(
        value = value,
        onValueChange = { value = it },
        label = { Text("Enter text") },
        maxLines = 2,
        textStyle = TextStyle(color = Color.Blue, fontWeight = FontWeight.Bold),
        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.

var text by remember { mutableStateOf("") }
val brush = remember {
    Brush.linearGradient(
        colors = rainbowColors
    )
}
TextField(
    value = text, onValueChange = { text = it }, textStyle = TextStyle(brush = brush)
)

استخدام buildAnnotatedString وSpanStyle، بالإضافة إلى linearGradient، لتخصيص جزء من النص فقط
الشكل 3. استخدام buildAnnotatedString وSpanStyle مع linearGradient لتخصيص جزء من النص فقط

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

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

  • capitalization
  • autoCorrect
  • keyboardType
  • imeAction

إدخال التنسيق

تسمح لك TextField بضبط VisualTransformation على قيمة الإدخال، مثل استبدال الأحرف بـ * لكلمات المرور، أو إدراج واصلة كل 4 أرقام لرقم بطاقة الائتمان:

@Composable
fun PasswordTextField() {
    var password by rememberSaveable { mutableStateOf("") }

    TextField(
        value = password,
        onValueChange = { password = it },
        label = { Text("Enter password") },
        visualTransformation = PasswordVisualTransformation(),
        keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Password)
    )
}

حقل إدخال نص كلمة المرور، مع إخفاء النص

تتوفّر المزيد من الأمثلة في رمز المصدر VisualTransformationSamples.

إدخال البيانات بدقة

من المهام الشائعة عند تعديل النص إزالة الأحرف البادئة أو تحويل سلسلة الإدخال بأي طريقة أخرى في كل مرة تتغيّر فيها.

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

لتنفيذ حقل نصي لا يسمح بالأصفار البادئة، يمكنك إجراء ذلك من خلال إزالة جميع الأصفار البادئة عند تغيير كل قيمة.

@Composable
fun NoLeadingZeroes() {
    var input by rememberSaveable { mutableStateOf("") }
    TextField(
        value = input,
        onValueChange = { newText ->
            input = newText.trimStart { it == '0' }
        }
    )
}

للتحكّم في موضع المؤشر أثناء تنظيف النص، استخدِم TextFieldValue التفريع الزائد TextField كجزء من الحالة.

أفضل الممارسات المتعلّقة بالحالة

في ما يلي سلسلة من أفضل الممارسات لتحديد وتعديل TextField state لمنع حدوث مشاكل في الإدخال في تطبيقك.

  • استخدام MutableState لتمثيل حالة TextField: تجنَّب استخدام مصادر البيانات التفاعلية مثل StateFlow لتمثيل حالة TextField، لأنّ هذه البنى قد تؤدي إلى حدوث تأخيرات غير متزامنة.

class SignUpViewModel : ViewModel() {

    var username by mutableStateOf("")
        private set

    /* ... */
}

  • تجنُّب التأخير في تعديل الحالة: عند استدعاء onValueChange، عدِّل TextField بشكل متزامن وفورًا:

// SignUpViewModel.kt

class SignUpViewModel(private val userRepository: UserRepository) : ViewModel() {

    var username by mutableStateOf("")
        private set

    fun updateUsername(input: String) {
        username = input
    }
}

// SignUpScreen.kt

@Composable
fun SignUpScreen(/*...*/) {

    OutlinedTextField(
        value = viewModel.username,
        onValueChange = { username -> viewModel.updateUsername(username) }
        /*...*/
    )
}

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