עורך שיטות קלט (IME) הוא אמצעי בקרה של משתמש שמאפשר למשתמשים להזין טקסט. Android מספק מסגרת להרחבת שיטות קלט שמאפשרת לאפליקציות לספק למשתמשים שיטות קלט חלופיות, כמו מקלדות במסך או קלט דיבור. אחרי התקנת רכיבי ה-IME, המשתמש יכול לבחור אחד מהם מההגדרות המערכת ולהשתמש בו בכל המערכת. אפשר להפעיל רק IME אחד בכל רגע נתון.
כדי להוסיף IME למערכת Android, יוצרים אפליקציית Android שמכילה כיתה שמרחיבה את InputMethodService
.
בנוסף, בדרך כלל יוצרים פעילות 'הגדרות' שמעבירה אפשרויות לשירות ה-IME. אפשר גם להגדיר ממשק משתמש של הגדרות שיוצג כחלק מהגדרות המערכת.
בדף הזה מפורטים הנושאים הבאים:
- מחזור החיים של IME
- הצהרה על רכיבי IME במניפסט של האפליקציה
- IME API
- עיצוב ממשק משתמש של IME
- שליחת טקסט מ-IME לאפליקציה
- עבודה עם סוגי משנה של IME
- שיקולים נוספים לגבי IME
אם זו הפעם הראשונה שאתם משתמשים בשיטות קלט מסך, מומלץ לקרוא קודם את המאמר שיטות קלט במסך.
מחזור החיים של IME
בתרשים הבא מתוארים שלבי מחזור החיים של 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 הלטיני מספק לקלט מספרי בפלטפורמת Android:
כששדה קלט מקבל את המיקוד וה-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, כפי שמוצג באיור הבא:
בחירת סוגי משנה של IME מההגדרות המערכת
המשתמש יכול גם לקבוע את אופן השימוש בסוגי המשנה בחלונית ההגדרות שפות וקלט בהגדרות המערכת:
מעבר בין תת-סוגים של IME
כדי לאפשר למשתמשים לעבור בקלות בין תת-סוגים של IME, אפשר לספק מקש מעבר, כמו סמל השפה בצורת גלובוס במקלדת. כך משתפרת נוחות השימוש במקלדת והיא נוחה יותר למשתמש. כדי להפעיל את המעבר הזה, מבצעים את השלבים הבאים:
- מגדירים את
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">
- קוראים ל-method
shouldOfferSwitchingToNextInputMethod()
. - אם השיטה מחזירה את הערך true, מציגים מפתח החלפה.
- כשהמשתמש מקשיב על מקש המעבר, צריך להפעיל את
switchToNextInputMethod()
ולהעביר את הערך false. ערך false מציין למערכת לטפל בכל תת-הסוגים באופן שווה, ללא קשר ל-IME שאליו הם שייכים. אם מציינים את הערך true, המערכת צריכה לעבור בסבב בין תת-סוגים ב-IME הנוכחי.
שיקולים כלליים לגבי IME
אלה כמה דברים נוספים שכדאי לקחת בחשבון כשמטמיעים את ה-IME:
- לספק למשתמשים דרך להגדיר אפשרויות ישירות מממשק המשתמש של ה-IME.
- צריך לספק למשתמשים דרך לעבור ל-IME אחר ישירות מממשק המשתמש של שיטת הקלט, כי יכול להיות שמותקנים במכשיר כמה IME.
- להציג במהירות את ממשק המשתמש של ה-IME. כדאי לטעון מראש או לטעון על פי דרישה משאבים גדולים כדי שהמשתמשים יראו את ה-IME ברגע שהם מקישים על שדה טקסט. שמירת משאבים ותצוגות במטמון להפעלות הבאות של שיטת הקלט.
- שחרור הקצאות זיכרון גדולות מיד אחרי שהחלון של שיטת הקלט מוסתר, כדי שלאפליקציות יהיה מספיק זיכרון לרוץ. שימוש בהודעה עם עיכוב כדי לפנות משאבים אם ה-IME מוסתר למשך כמה שניות.
- חשוב לוודא שהמשתמשים יכולים להזין כמה שיותר תווים בשפה או באזור הגיאוגרפי המשויכים ל-IME. יכול להיות שמשתמשים ישתמשו בסימני פיסוק בסיסמה או בשם המשתמש, ולכן ה-IME צריך לספק הרבה תווים שונים כדי לאפשר למשתמשים להזין סיסמה ולגשת למכשיר.