הגדרת שדות טקסט

TextField מאפשר למשתמשים להזין ולשנות טקסט. יש שני סוגים של שדות טקסט שאפשר להשתמש בהם: שדות טקסט מבוססי-מצב ושדות טקסט מבוססי-ערך. בוחרים את סוג התוכן שרוצים להציג:

מומלץ להשתמש בשדות טקסט שמבוססים על מצב, כי הם מספקים גישה מלאה ואמינה יותר לניהול המצב של TextField. בטבלה הבאה מפורטים ההבדלים בין סוגי שדות הטקסט האלה, וגם היתרונות העיקריים של שדות טקסט מבוססי-מצב:

Feature

שדות טקסט מבוססי-ערך

שדות טקסט לפי מדינה

הטבה לפי מדינה

ניהול מצבים

מעדכנת את המצב של שדה הטקסט באמצעות הקריאה החוזרת (callback) של onValueChange. באחריותך לעדכן את value במדינה שלך על סמך השינויים שדווחו על ידי onValueChange.

משתמש באופן מפורש באובייקט TextFieldState כדי לנהל את מצב קלט הטקסט (ערך, בחירה וקומפוזיציה). המצב הזה נשמר ואפשר לשתף אותו.

  • הקריאה החוזרת (callback) של 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:
    • סגנון ברירת המחדל הוא מלא
    • ‫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.

הנחיית סגנון באמצעות 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 בכל מקום שמתאים בארכיטקטורה שלכם. יש 2 מאפיינים עיקריים ש-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 ריק או להעביר ערך ראשוני שמייצג את ערך הטקסט באתחול. אם מועבר ערך אחר בהרכבה מחדש (recomposition) הבאה, הערך של המצב לא מתעדכן. כדי לעדכן את המצב אחרי שהוא מאותחל, צריך להפעיל שיטות עריכה ב-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()
        }
    }
}

טרנספורמציות של קלט שרשרת

כדי להוסיף כמה מסננים לקלט הטקסט, אפשר לשרשר InputTransformation באמצעות פונקציית התוסף then. המסננים מופעלים ברצף. מומלץ להפעיל קודם את המסננים הסלקטיביים ביותר, כדי להימנע מטרנספורמציות מיותרות של נתונים שבסופו של דבר יסוננו.

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

אחרי שמוסיפים טרנספורמציות של קלט, הקלט TextField יכול להכיל עד 10 ספרות.

עיצוב הקלט לפני שהוא מוצג

OutputTransformations let you format user input before it is rendered on the screen. בניגוד ל-InputTransformation, העיצוב שבוצע באמצעות OutputTransformation לא נשמר ב-TextFieldState. בהמשך לדוגמה הקודמת של מספר הטלפון, צריך להוסיף סוגריים ומקפים במקומות המתאימים:

מספר טלפון אמריקאי, בפורמט תקין עם סוגריים, מקפים ואינדקסים תואמים.
איור 3. מספר טלפון אמריקאי בפורמט תקין ועם האינדקסים המתאימים.

זו הדרך המעודכנת לטפל ב-VisualTransformation ב-TextField מבוססי-ערך, וההבדל העיקרי הוא שלא צריך לחשב את מיפויי ההיסט שלהם.

‫OutputTransformation הוא ממשק של שיטה מופשטת אחת. כדי להטמיע OutputTransformation בהתאמה אישית, צריך לשנות את ה-method‏ 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

מקורות מידע נוספים