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