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

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

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

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

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

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

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

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

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

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

במערכת Android, IME הוא אפליקציה ל-Android שמכילה שירות IME מיוחד. קובץ המניפסט של האפליקציה צריך להצהיר על השירות, לבקש את ההרשאות הנדרשות, לספק מסנן כוונה שתואמת לפעולה 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 לחשוף מצבי קלט מרובים ושפות שנתמכות על ידי 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 צריך לספק הרבה תווים שונים כדי לאפשר למשתמשים להזין סיסמה ולגשת למכשיר.