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

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

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

תכונה

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

שדות טקסט מבוססי-מצב

הטבה מבוססת-מדינה

ניהול המצב

עדכון המצב של שדה הטקסט באמצעות פונקציית ה-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:
    • עיצוב ברירת המחדל הוא filled
    • OutlinedTextField היא הגרסה עם הסגנון outlined
  2. BasicTextField מאפשר למשתמשים לערוך טקסט באמצעות מקלדת חומרה או תוכנה, אבל לא מספק קישוטים כמו רמז או placeholder.

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. עם זאת, צריך להשתמש ב-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 תוכנן כך שאפשר יהיה להעלות אותו לכל מקום בארכיטקטורה שלכם. יש 2 מאפיינים עיקריים ש-TextFieldState מספק:

  • initialText: התוכן של TextField.
  • initialSelection: מציין את המיקום הנוכחי של הסמן או של הבחירה.

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

אפשר להשתמש ב-TextFieldState() כדי להעביר את המצב ל-TextField. לשם כך, מומלץ להשתמש בפונקציה rememberTextFieldState(). rememberTextFieldState() יוצר את המכונה TextFieldState ב-composable, מוודא שאובייקט המצב נשמר ומספק פונקציונליות מובנית לשמירה ולשחזור:

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

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

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

שדה טקסט עם הטקסט 'שם משתמש' שמופיע בתוך שדה הטקסט.
איור 2. TextField עם 'שם משתמש' כטקסט הראשוני.

שינוי טקסט באמצעות TextFieldBuffer

TextFieldBuffer משמש כקונטיינר טקסט שניתן לעריכה, בדומה ל-StringBuilder. הוא מכיל גם את תוכן הטקסט וגם מידע על הבחירה הנוכחית.

לעיתים קרובות TextFieldBuffer מופיע כטווח מקלט בפונקציות כמו TextFieldState.edit,‏ InputTransformation.transformInput או OutputTransformation.transformOutput. בפונקציות האלה אפשר לקרוא או לעדכן את TextFieldBuffer לפי הצורך. לאחר מכן, השינויים האלה מועברים ל-TextFieldState או לצינור עיבוד הנתונים לעיבוד (render) במקרה של 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. מספר טלפון בארה"ב בפורמט הנכון עם אינדקסים תואמים.

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

OutputTransformation הוא ממשק של שיטה מופשטת אחת. כדי להטמיע OutputTransformation בהתאמה אישית, צריך לשנות את השיטה transformOutput:

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

כדי לעצב מספר טלפון, מוסיפים ל-OutputTransformation סוגריים פתוחים במדד 0, סוגריים סגורים במדד 4 וקו מפריד במדד 8:

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

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