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

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

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

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

אם לא עבדתם עם עורכי שיטות קלט, קודם כדאי לקרוא את המאמר המבוא שיטות קלט במסך.

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

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

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

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

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

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

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

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

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

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

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

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

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

תמונה שבה מוצג קלט מספרי ב-IME לטיני
איור 3. קלט מספרי של 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);

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

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

מבצעים קריאה ל-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>

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

בחירת סוגי משנה של IME מסרגל ההתראות

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

תמונה שמוצג בה תפריט המערכת &quot;שפות וקלט&quot;
איור 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. מבצעים קריאה ל-shouldOfferSwitchingToNextInputMethod().
  3. אם השיטה מחזירה את הערך True, מוצג מקש מעבר.
  4. כשהמשתמש לוחץ על מקש ההחלפה, צריך להפעיל את switchToNextInputMethod(), ולהעביר את הערך false. אם הערך הוא false, המערכת מתייחסת לכל סוגי המשנה באופן שווה, בלי קשר ל-IME שאליו הם שייכים. אם מציינים true, המערכת צריכה לעבור בין סוגי המשנה ב-IME הנוכחי.

שיקולים כלליים לגבי עורכי שיטות קלט (IME)

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

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