יצירה של שיטת קלט

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

כדי להוסיף IME למערכת Android, יוצרים אפליקציית Android שמכילה כיתה שמרחיבה את InputMethodService. בנוסף, בדרך כלל יוצרים פעילות 'הגדרות' שמעבירה אפשרויות לשירות ה-IME. אפשר גם להגדיר ממשק משתמש של הגדרות שיוצג כחלק מהגדרות המערכת.

בדף הזה מפורטים הנושאים הבאים:

אם זו הפעם הראשונה שאתם משתמשים בשיטות קלט מסך, מומלץ לקרוא קודם את המאמר שיטות קלט במסך.

מחזור החיים של IME

בתרשים הבא מתוארים שלבי מחזור החיים של IME:

תמונה שמראה את מחזור החיים של IME.
איור 1. מחזור החיים של IME.

בקטעים הבאים מוסבר איך מטמיעים את ממשק המשתמש ואת הקוד שמשויכים ל-IME שעומד במחזור החיים הזה.

הצהרת רכיבי IME במניפסט

במערכת Android, IME הוא אפליקציה ל-Android שמכילה שירות IME מיוחד. קובץ המניפסט של האפליקציה צריך להצהיר על השירות, לבקש את ההרשאות הנדרשות, לספק מסנן Intent שתואם לפעולה action.view.InputMethod ולספק מטא-נתונים שמגדירים את המאפיינים של ה-IME. בנוסף, כדי לספק ממשק הגדרות שמאפשר למשתמש לשנות את ההתנהגות של ה-IME, אפשר להגדיר פעילות 'הגדרות' שאפשר להפעיל מתוך הגדרות המערכת.

קטע הקוד הבא מכריז על שירות IME. הוא מבקש את ההרשאה BIND_INPUT_METHOD כדי לאפשר לשירות לחבר את ה-IME למערכת, מגדיר מסנן כוונה שתואמת לפעולה android.view.InputMethod ומגדיר מטא-נתונים ל-IME:

<!-- Declares the input method service. -->
<service android:name="FastInputIME"
    android:label="@string/fast_input_label"
    android:permission="android.permission.BIND_INPUT_METHOD">
    <intent-filter>
        <action android:name="android.view.InputMethod" />
    </intent-filter>
    <meta-data android:name="android.view.im"
               android:resource="@xml/method" />
</service>

קטע הקוד הבא מכריז על פעילות ההגדרות של ה-IME. יש לו מסנן Intent עבור ACTION_MAIN שמציין שהפעילות הזו היא נקודת הכניסה הראשית לאפליקציית ה-IME:

<!-- Optional: an activity for controlling the IME settings. -->
<activity android:name="FastInputIMESettings"
    android:label="@string/fast_input_settings">
    <intent-filter>
        <action android:name="android.intent.action.MAIN"/>
    </intent-filter>
</activity>

אפשר גם לספק גישה להגדרות ה-IME ישירות מממשק המשתמש שלו.

ה-API של שיטת הקלט

הכיתות הספציפיות ל-IME נמצאות בחבילות android.inputmethodservice ו-android.view.inputmethod. הכיתה KeyEvent חשובה לטיפול בתווים במקלדת.

החלק המרכזי של IME הוא רכיב שירות – כיתה שמרחיבה את InputMethodService. בנוסף להטמעת מחזור החיים הרגיל של השירות, בכיתה הזו יש קריאות חוזרות (callbacks) שמספקות את ממשק המשתמש של ה-IME, מטפלות בקלט של המשתמש ומעבירות טקסט לשדה שמקבל את המיקוד. כברירת מחדל, הכיתה InputMethodService מספקת את רוב ההטמעה לניהול המצב והחשיפה של ה-IME ולתקשורת עם שדה הקלט הנוכחי.

גם הכיתות הבאות חשובות:

BaseInputConnection
הגדרת ערוץ התקשורת מ-InputMethod חזרה לאפליקציה שמקבלת את הקלט שלה. משתמשים בו כדי לקרוא טקסט סביב הסמן, לאשר את הטקסט בתיבת הטקסט ולשלוח לאפליקציה אירועים מרכזיים גולמיים. אפליקציות צריכות להרחיב את המחלקה הזו במקום להטמיע את הממשק הבסיסי InputConnection.
KeyboardView
תוסף של View שמציג מקלדת ומגיב לאירועי קלט של משתמשים. פריסת המקלדת מצוינה באמצעות מופע של Keyboard, שאפשר להגדיר בקובץ XML.

עיצוב ממשק המשתמש של שיטת הקלט

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

תצוגת הקלט

תצוגת הקלט היא ממשק המשתמש שבו המשתמש מזין טקסט באמצעות הקשות על מקש, כתב יד או תנועות. כשה-IME מוצג בפעם הראשונה, המערכת קוראת ל-callback‏ onCreateInputView(). כשמפעילים את השיטה הזו, יוצרים את הפריסה שרוצים להציג בחלון ה-IME ומחזירים את הפריסה למערכת. קטע הקוד הבא מציג דוגמה להטמעה של השיטה onCreateInputView():

Kotlin

override fun onCreateInputView(): View {
    return layoutInflater.inflate(R.layout.input, null).apply {
        if (this is MyKeyboardView) {
            setOnKeyboardActionListener(this@MyInputMethod)
            keyboard = latinKeyboard
        }
    }
}

Java

@Override
public View onCreateInputView() {
    MyKeyboardView inputView =
        (MyKeyboardView) getLayoutInflater().inflate(R.layout.input, null);

    inputView.setOnKeyboardActionListener(this);
    inputView.setKeyboard(latinKeyboard);

    return inputView;
}

בדוגמה הזו, MyKeyboardView הוא מופע של הטמעה בהתאמה אישית של KeyboardView שמניב Keyboard.

תצוגת המועמדים

תצוגת המועמדים היא ממשק המשתמש שבו מוצגות תיקונים אפשריים של מילים או הצעות למילים ב-IME, והמשתמש יכול לבחור מתוכן. במהלך מחזור החיים של ה-IME, המערכת קוראת ל-onCreateCandidatesView() כשהיא מוכנה להציג את תצוגת המועמדים. בהטמעה של השיטה הזו, צריך להחזיר פריסה שמציגה הצעות למילים, או להחזיר null אם לא רוצים להציג שום דבר. תגובה null היא התנהגות ברירת המחדל, כך שאין צורך להטמיע אותה אם לא מספקים הצעות.

שיקולים בתכנון ממשק המשתמש

בקטע הזה מתוארים כמה שיקולים לגבי עיצוב ממשק המשתמש של IME.

טיפול במספר גדלים של מסכים

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

טיפול בסוגים שונים של קלט

שדות טקסט ב-Android מאפשרים להגדיר סוג קלט ספציפי, כמו טקסט בפורמט חופשי, מספרים, כתובות URL, כתובות אימייל ומחרוזות חיפוש. כשמטמיעים IME חדש, צריך לזהות את סוג הקלט של כל שדה ולספק את הממשק המתאים לו. עם זאת, אין צורך להגדיר את ה-IME כך שיבדוק אם המשתמש מזין טקסט תקין לסוג הקלט. זוהי האחריות של האפליקציה שבבעלותה שדה הטקסט.

לדוגמה, זהו הממשק ש-IME הלטיני מספק להזנת הטקסט בפלטפורמת Android:

תמונה שמראה קלט טקסט ב-IME לטינית
איור 2. קלט טקסט של IME לטינית.

זהו הממשק ש-IME הלטיני מספק לקלט מספרי בפלטפורמת Android:

תמונה שמראה קלט מספרי ב-IME לטינית
איור 3. קלט מספרי של IME לטינית.

כששדה קלט מקבל את המיקוד וה-IME מתחיל לפעול, המערכת קוראת ל-onStartInputView() ומעבירה אובייקט EditorInfo שמכיל פרטים על סוג הקלט ומאפיינים אחרים של שדה הטקסט. באובייקט הזה, השדה inputType מכיל את סוג הקלט של שדה הטקסט.

השדה inputType הוא int שמכיל דפוסי ביט להגדרות שונות של סוג הקלט. כדי לבדוק את סוג הקלט של שדה הטקסט, מסתירים אותו בעזרת הקבוע TYPE_MASK_CLASS, כך:

Kotlin

inputType and InputType.TYPE_MASK_CLASS

Java

inputType & InputType.TYPE_MASK_CLASS

תבנית הביטים של סוג הקלט יכולה להיות אחת מכמה ערכים, כולל:

TYPE_CLASS_NUMBER
שדה טקסט להזנת מספרים. כפי שמוצג באיור 3, ב-IME הלטיני מוצג מקלדת מספרים בשדות מהסוג הזה.
TYPE_CLASS_DATETIME
שדה טקסט להזנת תאריך ושעה.
TYPE_CLASS_PHONE
שדה טקסט להזנת מספרי טלפון.
TYPE_CLASS_TEXT
שדה טקסט להזנת תווים נתמכים.

הקבועים האלה מתוארים בפירוט רב יותר במסמכי העזרה של InputType.

השדה inputType יכול להכיל ביטים אחרים שמציינים וריאנט של סוג שדה הטקסט, כמו:

TYPE_TEXT_VARIATION_PASSWORD
גרסה של TYPE_CLASS_TEXT להזנת סיסמאות. שיטת הקלט מציגה סמלי דינגו במקום את הטקסט בפועל.
TYPE_TEXT_VARIATION_URI
וריאנט של TYPE_CLASS_TEXT להזנת כתובות URL של אתרים ומזהי משאבים אחידים (URI) אחרים.
TYPE_TEXT_FLAG_AUTO_COMPLETE
וריאנט של TYPE_CLASS_TEXT להזנת טקסט שהאפליקציה ממלאת באופן אוטומטי ממילון, מחיפוש או מכלי אחר.

כשבודקים את הווריאציות האלה, מסתירים את inputType בעזרת הקבוע המתאים. המשתנים הקבועים הזמינים של המסכה מפורטים במסמכי העזרה של InputType.

שליחת טקסט לאפליקציה

כשהמשתמש מזין טקסט באמצעות ה-IME, אפשר לשלוח טקסט לאפליקציה על ידי שליחת אירועי מקש בודדים או על ידי עריכת הטקסט סביב הסמן בשדה הטקסט של האפליקציה. בכל מקרה, צריך להשתמש במכונה של InputConnection כדי להעביר את הטקסט. כדי לקבל את המופע הזה, צריך להפעיל את הפונקציה InputMethodService.getCurrentInputConnection().

עורכים את הטקסט שמסביב לסמן העכבר

כשעורכים טקסט קיים, יש כמה שיטות שימושיות ב-BaseInputConnection:

getTextBeforeCursor()
מחזירה CharSequence שמכיל את מספר התווים המבוקשים לפני מיקום הסמן הנוכחי.
getTextAfterCursor()
מחזירה CharSequence שמכיל את מספר התווים המבוקשים אחרי מיקום הסמן הנוכחי.
deleteSurroundingText()
מחיקת מספר התווים שצוין לפני מיקום הסמן הנוכחי ואחריו.
commitText()
שומרת את הערך CharSequence בשדה הטקסט ומגדירה מיקום חדש לסמן.

לדוגמה, קטע הקוד הבא מראה איך מחליפים את ארבעת התווים שמשמאל לסמן הקליע בטקסט 'שלום!':

Kotlin

currentInputConnection.also { ic: InputConnection ->
    ic.deleteSurroundingText(4, 0)
    ic.commitText("Hello", 1)
    ic.commitText("!", 1)
}

Java

InputConnection ic = getCurrentInputConnection();
ic.deleteSurroundingText(4, 0);
ic.commitText("Hello", 1);
ic.commitText("!", 1);

תמיכה בכתיבת טקסט לפני אישור

אם ה-IME מנבא טקסט או נדרש לבצע כמה שלבים כדי ליצור גליף או מילה, אפשר להציג את ההתקדמות בשדה הטקסט עד שהמשתמש יאשר את המילה, ואז להחליף את היצירה החלקית בטקסט המלא. כדי להעניק לטקסט טיפול מיוחד, אפשר להוסיף לו span כשמעבירים אותו אל setComposingText().

קטע הקוד הבא מדגים איך להציג את ההתקדמות בשדה טקסט:

Kotlin

currentInputConnection.also { ic: InputConnection ->
    ic.setComposingText("Composi", 1)
    ic.setComposingText("Composin", 1)
    ic.commitText("Composing ", 1)
}

Java

InputConnection ic = getCurrentInputConnection();
ic.setComposingText("Composi", 1);
ic.setComposingText("Composin", 1);
ic.commitText("Composing ", 1);

תיעוד אירועים מרכזיים של חומרה

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

כדי ליירט מפתחות חומרה, משנים את הערכים של onKeyDown() ו-onKeyUp().

צריך לקרוא ל-method‏ super() עבור מפתחות שאתם לא רוצים לטפל בהם בעצמכם.

יצירת תת-סוג של IME

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

  • לוקאל, למשל en_US או fr_FR
  • מצב קלט, כמו קול, מקלדת או כתב יד
  • סגנונות קלט, טפסים או מאפיינים אחרים שספציפיים ל-IME, כמו פריסות של מקלדות עם 10 מקשים או מקלדות QWERTY

המצב יכול להיות כל טקסט, כמו 'מקלדת' או 'קול'. סוג משנה יכול גם לחשוף שילוב של אלה.

המידע על הסוג המשני משמש לתיבת הדו-שיח של מחליף ה-IME שזמינה בסרגל ההתראות, וגם להגדרות ה-IME. המידע הזה גם מאפשר למסגרת להציג ישירות תת-סוג ספציפי של IME. כשאתם יוצרים IME, כדאי להשתמש בתכונה של תת-סוגים, כי היא עוזרת למשתמש לזהות שפות ומצבים שונים של IME ולעבור ביניהם.

מגדירים את הסוגים המשניים באחד מקובצי המשאבים של שיטת הקלט בפורמט XML, באמצעות הרכיב <subtype>. קטע הקוד הבא מגדיר IME עם שני תת-סוגים: תת-סוג של מקלדת לאזור הלשוני אנגלית (ארה"ב) ותת-סוג אחר של מקלדת לאזור הלשוני צרפתית (צרפת):

<input-method xmlns:android="http://schemas.android.com/apk/res/android"
        android:settingsActivity="com.example.softkeyboard.Settings"
        android:icon="@drawable/ime_icon">
    <subtype android:name="@string/display_name_english_keyboard_ime"
            android:icon="@drawable/subtype_icon_english_keyboard_ime"
            android:languageTag="en-US"
            android:imeSubtypeMode="keyboard"
            android:imeSubtypeExtraValue="somePrivateOption=true" />
    <subtype android:name="@string/display_name_french_keyboard_ime"
            android:icon="@drawable/subtype_icon_french_keyboard_ime"
            android:languageTag="fr-FR"
            android:imeSubtypeMode="keyboard"
            android:imeSubtypeExtraValue="someVariable=30,someInternalOption=false" />
    <subtype android:name="@string/display_name_german_keyboard_ime" ... />
</input-method>

כדי לוודא שסוגי המשנה מסומנים בצורה נכונה בממשק המשתמש, צריך להשתמש ב-‎%s כדי לקבל תווית של סוג משנה זהה לתווית הלוקאל של סוג המשנה. שני קטעי הקוד הבאים מדגימים את זה. בקטע הקוד הראשון מוצג חלק מקובץ ה-XML של שיטת הקלט:

<subtype
    android:label="@string/label_subtype_generic"
    android:imeSubtypeLocale="en_US"
    android:icon="@drawable/icon_en_us"
    android:imeSubtypeMode="keyboard" />

קטע הקוד הבא הוא חלק מקובץ strings.xml של ה-IME. משאב המחרוזת label_subtype_generic, שמשמש להגדרת התווית של תת-הסוג בהגדרת ממשק המשתמש של שיטת הקלט, מוגדר באופן הבא:

<string name="label_subtype_generic">%s</string>

ההגדרה הזו גורמת לשם התצוגה של תת-הסוג להתאים להגדרת האזור. לדוגמה, בכל לוקל של אנגלית, השם המוצג הוא 'אנגלית (ארה"ב)'.

בחירת תת-סוגים של IME בסרגל ההתראות

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

תמונה שמוצג בה התפריט &#39;שפות וקלט&#39; במערכת
איור 4. תפריט המערכת שפות וקלט.

בחירת סוגי משנה של IME מההגדרות המערכת

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

תמונה שבה מוצג התפריט לבחירת שפות
איור 5. תפריט המערכת שפות

מעבר בין תת-סוגים של IME

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

  1. מגדירים את supportsSwitchingToNextInputMethod = "true" בקובצי המשאבים של שיטת הקלט בפורמט XML. ההצהרה צריכה להיראות כמו קטע הקוד הבא:
    <input-method xmlns:android="http://schemas.android.com/apk/res/android"
            android:settingsActivity="com.example.softkeyboard.Settings"
            android:icon="@drawable/ime_icon"
            android:supportsSwitchingToNextInputMethod="true">
    
  2. קוראים ל-method‏ shouldOfferSwitchingToNextInputMethod().
  3. אם השיטה מחזירה את הערך true, מציגים מפתח החלפה.
  4. כשהמשתמש מקשיב על מקש המעבר, צריך להפעיל את switchToNextInputMethod() ולהעביר את הערך false. ערך false מציין למערכת לטפל בכל תת-הסוגים באופן שווה, ללא קשר ל-IME שאליו הם שייכים. אם מציינים את הערך true, המערכת צריכה לעבור בסבב בין תת-סוגים ב-IME הנוכחי.

שיקולים כלליים לגבי IME

אלה כמה דברים נוספים שכדאי לקחת בחשבון כשמטמיעים את ה-IME:

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