במכשירים עם מסכים גדולים, המשתמשים לרוב יוצרים אינטראקציה עם האפליקציות באמצעות מקלדת, עכבר, משטח מגע, סטיילוס או גיימפאד. כדי לאפשר לאפליקציה לקבל קלט ממכשירים חיצוניים:
- בודקים את התמיכה הבסיסית במקלדת, כמו Ctrl+Z כדי לבטל פעולה, Ctrl+C כדי להעתיק ו-Ctrl+S כדי לשמור. בקישור הבא תוכלו למצוא רשימה של מקשי הקיצור שמוגדרים כברירת מחדל: טיפול בפעולות במקלדת.
- בודקים את התמיכה המתקדמת במקלדת, למשל: ניווט במקלדת באמצעות מקש Tab ומקשות החיצים, אישור הזנת טקסט באמצעות מקש Enter והפעלה והשהיה של אפליקציות מדיה באמצעות מקש הרווח.
- בדיקת אינטראקציות בסיסיות עם העכבר, כולל לחיצה ימנית כדי לפתוח תפריט הקשר, שינויים בסמלים במצב של עכבר מרחף ואירועי גלילה בעכבר או בלוח המגע ברכיבים מותאמים אישית.
- בדיקת מכשירי קלט ספציפיים לאפליקציה, כמו עט, בקרי משחקים ובקרי MIDI לאפליקציות מוזיקה.
- כדאי להוסיף תמיכה בהזנת נתונים מתקדמת שיכולה להבליט את האפליקציה בסביבות מחשב. לדוגמה, אפשר להשתמש במשטח מגע כמעבר רך (cross-fader) באפליקציות לדי ג'יי, בצילום של תנועות העכבר במשחקים ובמקשי קיצור למשתמשים שמשתמשים במקלדת.
מקלדת
האופן שבו האפליקציה מגיבה להקלדה במקלדת משפיע על חוויית המשתמש במסך הגדול. יש שלושה סוגים של קלט מקלדת: ניווט, לחיצות מקש ומקשי קיצור.
ניווט
ניווט במקלדת מוטמע לעיתים רחוקות באפליקציות שמתמקדות במגע, אבל משתמשים מצפים לכך כשהם משתמשים באפליקציה והידיים שלהם על המקלדת. ניווט במקלדת יכול להיות חיוני בטלפונים, בטאבלטים, במכשירים מתקפלים ובמכשירים למחשב למשתמשים עם צרכים של נגישות.
באפליקציות רבות, המערכת של Android מטפלת באופן אוטומטי בניווט באמצעות מקשי החצים ומקש Tab. לדוגמה, אפשר להתמקד ב-Button
כברירת מחדל, ובדרך כלל הניווט באמצעות המקלדת אמור לפעול בלי קוד נוסף. כדי להפעיל ניווט במקלדת בתצוגות שלא ניתן להתמקד בהן כברירת מחדל, צריך לסמן אותן כניתנות למיקוד. אפשר לעשות זאת באופן פרוגרמטי או ב-XML:
Kotlin
yourView.isFocusable = true
Java
yourView.setFocusable(true);
לחלופין, אפשר להגדיר את המאפיין focusable
בקובץ הפריסה:
android:focusable="true"
מידע נוסף זמין במאמר טיפול בפוקוס.
כשהמיקוד מופעל, מסגרת Android יוצרת מיפוי ניווט לכל התצוגות שניתן להתמקד בהן על סמך המיקום שלהן. בדרך כלל זה עובד כמצופה ואין צורך בפיתוח נוסף. אם מיפוי ברירת המחדל לא מתאים לצרכים של האפליקציה, אפשר לשנות את המיפוי באופן הבא:
Kotlin
// Arrow keys yourView.nextFocusLeftId = R.id.view_to_left yourView.nextFocusRightId = R.id.view_to_right yourView.nextFocusTopId = R.id.view_above yourView.nextFocusBottomId = R.id.view_below // Tab key yourView.nextFocusForwardId = R.id.next_view
Java
// Arrow keys yourView.setNextFocusLeftId(R.id.view_to_left); yourView.setNextFocusRightId(R.id.view_to_left); yourView.setNextFocusTopId(R.id.view_to_left); yourView.setNextFocusBottomId(R.id.view_to_left); // Tab key yourView.setNextFocusForwardId(R.id.next_view);
בודקים את הגישה לכל רכיב בממשק המשתמש של האפליקציה באמצעות המקלדת בלבד. אלמנטים שנמצאים בשימוש תדיר צריכים להיות נגישים ללא קלט מהעכבר או ממגע.
חשוב לזכור שתמיכה במקלדת עשויה להיות חיונית למשתמשים עם צרכים מיוחדים.
הקשות
לגבי קלט טקסט שיטופל על ידי מקלדת וירטואלית במסך (IME), כמו, EditText
ו-, האפליקציות אמורות לפעול כצפוי במכשירים עם מסכים גדולים בלי צורך בפיתוח נוסף. באפליקציות צריך לטפל בעצמן בהתנהגות של הקשות על המקלדת שלא ניתן לצפות מראש במסגרת. הדבר נכון במיוחד לאפליקציות עם תצוגות בהתאמה אישית.
דוגמאות לכך הן אפליקציות צ'אט שמשתמשות במקש Enter כדי לשלוח הודעה, אפליקציות מדיה שמתחילות ומפסיקות את ההפעלה באמצעות מקש הרווח ומשחקים שבהם שולטים בתנועה באמצעות המקשים w, a, s ו-d.
רוב האפליקציות משנות את קריאת החזרה (callback) של onKeyUp()
ומוסיפות את ההתנהגות הצפויה לכל קוד מקש שהתקבל:
Kotlin
override fun onKeyUp(keyCode: Int, event: KeyEvent): Boolean { return when (keyCode) { KeyEvent.KEYCODE_ENTER -> { sendChatMessage() true } KeyEvent.KEYCODE_SPACE -> { playOrPauseMedia() true } else -> super.onKeyUp(keyCode, event) } }
Java
@Override public boolean onKeyUp(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_ENTER) { sendMessage(); return true; } else if (KeyEvent.KEYCODE_SPACE){ playOrPauseMedia(); return true; } else { return super.onKeyUp(keyCode, event); } }
אירוע onKeyUp
מתרחש כשמפעילים מקש ומפסיקים ללחוץ עליו. השימוש בקריאה החוזרת מונעת מהאפליקציות צורך לעבד מספר אירועים של onKeyDown
אם מקישים על מקש או משחררים אותו לאט. משחקים ואפליקציות שצריכים לזהות את הרגע שבו מקישים על מקש או אם המשתמש לוחץ על מקש ומוחזק אותו יכולים להאזין לאירוע onKeyDown
ולטפל באירועי onKeyDown
חוזרים בעצמם.
מידע נוסף זמין במאמר טיפול בפעולות מקלדת.
קיצורי דרך
כשמשתמשים במקלדת חומרה, מקשי הקיצור הנפוצים שכוללים את המקשים Ctrl, Alt, Shift ו-Meta אמורים לפעול. אם באפליקציה לא מופעלים מקשי קיצור, חוויית השימוש בה עלולה להיות מתסכלת למשתמש. משתמשים מתקדמים גם מעריכים קיצורי דרך למשימות ספציפיות לאפליקציה שמשמשות אותם לעיתים קרובות. קיצורי דרך מאפשרים להשתמש באפליקציה בקלות רבה יותר ומבדילים אותה מאפליקציות שאין להן קיצורי דרך.
מקשי קיצור נפוצים כוללים את Ctrl+S (שמירה), Ctrl+Z (ביטול) ו-Ctrl+Shift+Z (ביצוע מחדש). רשימה של מקשי הקיצור שמוגדרים כברירת מחדל מופיעה במאמר טיפול בפעולות במקלדת.
כדי להפעיל מקשי קיצור, אפשר להטמיע את dispatchKeyShortcutEvent()
כדי ליירט את כל שילובי המקשים (Alt, Ctrl, Shift ו-Meta) עבור קוד מקש נתון.
כדי לבדוק אם מקש צירוף ספציפי נלחץ, משתמשים ב-:
KeyEvent.isCtrlPressed()
,KeyEvent.isShiftPressed()
,KeyEvent.isAltPressed()
,KeyEvent.isMetaPressed()
, או
Kotlin
override fun dispatchKeyShortcutEvent(event: KeyEvent): Boolean { return when (event.keyCode) { KeyEvent.KEYCODE_O -> { openFile() // Ctrl+O, Shift+O, Alt+O true } KeyEvent.KEYCODE_Z-> { if (event.isCtrlPressed) { if (event.isShiftPressed) { redoLastAction() // Ctrl+Shift+Z pressed true } else { undoLastAction() // Ctrl+Z pressed true } } } else -> { return super.dispatchKeyShortcutEvent(event) } } }
Java
@Override public boolean dispatchKeyShortcutEvent(KeyEvent event) { if (event.getKeyCode() == KeyEvent.KEYCODE_O) { openFile(); // Ctrl+O, Shift+O, Alt+O return true; } else if(event.getKeyCode() == KeyEvent.KEYCODE_Z) { if (event.isCtrlPressed()) { if (event.isShiftPressed()) { redoLastAction(); return true; } else { undoLastAction(); return true; } } } return super.dispatchKeyShortcutEvent(event); }
הפרדה של קוד קיצור דרך מהטיפול בלחיצות מקש אחרות (כמו onKeyUp()
ו-onKeyDown()
) מאפשרת להשתמש במקשי שינוי כברירת מחדל, בלי צורך להטמיע בדיקות של מקשי שינוי בכל מקרה. הרשאה לכל השילובים של מקשי השינוי יכולה גם להיות נוחה יותר למשתמשים רגילים למערכות הפעלה ולפריסות מקלדת שונות.
עם זאת, אפשר גם להטמיע קיצורי דרך ב-onKeyUp()
על ידי בדיקה של KeyEvent.isCtrlPressed()
, KeyEvent.isShiftPressed()
או KeyEvent.isAltPressed()
. קל יותר לשמור על כך אם התנהגות המקש ששונתה היא שינוי בהתנהגות האפליקציה יותר מאשר קיצור דרך. לדוגמה, במשחקים שבהם W פירושו 'הליכה קדימה' ו-Shift+W פירושו 'ריצה קדימה'.
Kotlin
override fun onKeyUp(keyCode: Int, event: KeyEvent): Boolean { return when(keyCode) { KeyEvent.KEYCODE_W-> { if (event.isShiftPressed) { if (event.isCtrlPressed) { flyForward() // Ctrl+Shift+W pressed true } else { runForward() // Shift+W pressed true } } else { walkForward() // W pressed true } } else -> super.onKeyUp(keyCode, event) } }
Java
@Override public boolean onKeyUp(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_W) { if (event.isShiftPressed()) { if (event.isCtrlPressed()) { flyForward(); // Ctrl+Shift+W pressed return true; } else { runForward(); // Shift+W pressed return true; } } else { walkForward(); return true; } } return super.onKeyUp(keyCode, event); }
אפשר לעיין גם בכלי העזר למקשי הקיצור.
סטיילוס
הרבה מכשירים עם מסך גדול מגיעים עם עט stylus. אפליקציות ל-Android מטפלות בעטים כקלט במסך מגע. במכשירים מסוימים יכול להיות גם שולחן ציור עם חיבור USB או Bluetooth, כמו Wacom Intuos. אפליקציות ל-Android יכולות לקבל קלט ב-Bluetooth, אבל לא קלט ב-USB.
אירוע של עט מגע מדווח כאירוע של מסך מגע על ידי View#onTouchEvent()
או View#onGenericMotionEvent()
, ומכיל MotionEvent#getSource()
מסוג SOURCE_STYLUS
.
האובייקט MotionEvent
מכיל מידע על האירוע:
- הפונקציה
MotionEvent#getToolType()
מחזירה את הערכיםTOOL_TYPE_FINGER
,TOOL_TYPE_STYLUS
אוTOOL_TYPE_ERASER
, בהתאם לכלי שנגע במסך MotionEvent#getPressure()
מדווח על הלחץ הפיזי שמופעל על עט הסtylus (אם יש תמיכה)MotionEvent#getAxisValue()
עםMotionEvent.AXIS_TILT
ו-MotionEvent.AXIS_ORIENTATION
מספקים את הטיה הפיזית והכיוון של עט הסtylus (אם יש תמיכה)
נקודות היסטוריות
מערכת Android אוספת אירועי קלט ומעבירה אותם פעם אחת לכל מסגרת. עט יכול לדווח על אירועים בתדירויות גבוהות בהרבה מאשר המסך. כשאתם יוצרים אפליקציות ציור, אתם יכולים לבדוק אם קרו אירועים בעבר הקרוב באמצעות ממשקי ה-API של getHistorical
:
MotionEvent#getHistoricalX()
MotionEvent#getHistoricalY()
MotionEvent#getHistoricalPressure()
MotionEvent#getHistoricalAxisValue()
דחייה של Palm
כשמשתמשים מציירים, כותבים או מבצעים פעולות באפליקציה באמצעות סטיילוס, לפעמים הם נוגעים במסך בכף היד. אפשר לדווח לאפליקציה על אירוע המגע (מוגדרת ל-ACTION_DOWN
או ל-ACTION_POINTER_DOWN
) לפני שהמערכת מזהה את המגע המקרי בכף היד ומתעלם ממנו.
מערכת Android מבטלת אירועי נגיעה בכף היד על ידי שליחת אירוע MotionEvent
. אם האפליקציה מקבלת את האירוע ACTION_CANCEL
, צריך לבטל את התנועה. אם האפליקציה שלכם מקבלת את ההודעה ACTION_POINTER_UP
, בודקים אם ההגדרה FLAG_CANCELED
מוגדרת. אם כן, צריך לבטל את התנועה.
אין לבדוק רק את FLAG_CANCELED
. ב-Android 13 (רמת API 33) ואילך, המערכת מגדירה את הדגל FLAG_CANCELED
לאירועים מסוג ACTION_CANCEL
, אבל היא לא מגדירה את הדגל בגרסאות Android ישנות יותר.
12 Android
ב-Android 12 (רמת API 32) ובגרסאות ישנות יותר, אפשר לזהות דחיית כף יד רק באירועי מגע עם נקודת אצבע אחת. אם מגע כף היד הוא היחיד שמצביע על אירוע, המערכת מבטלת את האירוע על ידי הגדרת ACTION_CANCEL
באובייקט של אירוע התנועה. אם יש מצבעים אחרים שמופעלים, המערכת מגדירה את הערך ACTION_POINTER_UP
, שהוא לא מספיק לזיהוי דחייה של כף היד.
Android 13
ב-Android 13 (API ברמה 33) ואילך, אם מגע כף היד הוא היחיד שמצביע, המערכת מבטלת את האירוע על ידי הגדרת ACTION_CANCEL
ו-FLAG_CANCELED
באובייקט של אירוע התנועה. אם יש עוד נקודות ציון שנמצאות בסטטוס 'מושבת', המערכת מגדירה את הערכים של ACTION_POINTER_UP
ו-FLAG_CANCELED
.
בכל פעם שהאפליקציה מקבלת אירוע תנועה עם ACTION_POINTER_UP
, צריך לבדוק אם יש FLAG_CANCELED
כדי לקבוע אם האירוע מציין דחייה על ידי כף היד (או ביטול אירוע אחר).
אפליקציות לרישום הערות
ל-ChromeOS יש כוונה מיוחדת שמציגה למשתמשים אפליקציות רשומות לכתיבה ביומן. כדי לרשום אפליקציה כאפליקציית הערות, מוסיפים את הפרטים הבאים למניפסט של האפליקציה:
<intent-filter>
<action android:name="org.chromium.arc.intent.action.CREATE_NOTE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
כשאפליקציה רשומה במערכת, המשתמש יכול לבחור אותה כאפליקציית ברירת המחדל לכתיבה ביומן. כשמבקשים ליצור הערה חדשה, האפליקציה אמורה ליצור הערה ריקה שאפשר להזין בה באמצעות עט. כשהמשתמש רוצה להוסיף הערות לתמונה (למשל צילום מסך או תמונה שהורדתם), האפליקציה מופעלת עם ClipData
שמכיל פריט אחד או יותר עם מזהי URI מסוג content://
. האפליקציה אמורה ליצור הערה שבה התמונה הראשונה שצורפה משמשת כתמונת רקע, ולהיכנס למצב שבו המשתמש יכול לצייר על המסך בעזרת עט.
בדיקת כוונת כתיבת הערות ללא סטיילוס
[TBD remove section.]
כדי לבדוק אם אפליקציה מגיבה בצורה נכונה לכוונות ליצירת הערות בלי עט פעיל, משתמשים בשיטה הבאה כדי להציג את אפשרויות הכתיבה ב-ChromeOS:
- מעבר למצב פיתוח והפעלת הרשאת כתיבה במכשיר
- מקישים על Ctrl+Alt+F2 כדי לפתוח מסוף.
- מריצים את הפקודה
sudo vi /etc/chrome_dev.conf
- לוחצים על
i
כדי לערוך ולהוסיף את--ash-enable-palette
לשורה חדשה בסוף הקובץ - כדי לשמור, מקישים על Esc ואז מקלידים :, w, q ומקישים על Enter.
- לוחצים על Ctrl+Alt+F1 כדי לחזור לממשק המשתמש הרגיל של ChromeOS.
- יוצאים מהחשבון ונכנסים אליו שוב.
עכשיו אמור להופיע תפריט של עט במדף:
- מקישים על לחצן העט על המדף ובוחרים באפשרות הערה חדשה. אמורה להיפתח הערה ריקה לציור.
- מצלמים את המסך. במדף, בוחרים באפשרות לחצן הסטיילוס > צילום מסך או מורידים תמונה. בהתראה אמורה להופיע האפשרות הוספת הערות לתמונה. הפעולה הזו אמורה להפעיל את האפליקציה עם התמונה מוכנה להוספת הערות.
תמיכה בעכבר ובלוח מגע
בדרך כלל, רוב האפליקציות צריכות לטפל רק בשלושה אירועים שמתמקדים במסך גדול: לחיצה ימנית, החזקה וגרירה ושחרור.
לחיצה ימנית
כל פעולה שגורמת לאפליקציה להציג תפריט הקשר, כמו לחיצה ארוכה על פריט ברשימה, אמורה להגיב גם לאירועי לחיצה ימנית.
כדי לטפל באירועים של לחיצה ימנית, האפליקציות צריכות לרשום אירוע View.OnContextClickListener
:
Kotlin
yourView.setOnContextClickListener { showContextMenu() true }
Java
yourView.setOnContextClickListener(v -> { showContextMenu(); return true; });
פרטים על בניית תפריטי הקשר זמינים במאמר יצירת תפריט הקשר.
ריחוף
כדי שהפריסות של האפליקציה יהיו מבריקות וקלות יותר לשימוש, אתם יכולים לטפל באירועי מעוף מעל. זה נכון במיוחד לגבי רכיבי צפיות:
Kotlin
// Change the icon to a "hand" pointer on hover. // Highlight the view by changing the background. yourView.setOnHoverListener { view, _ -> addVisualHighlighting(true) view.pointerIcon = PointerIcon.getSystemIcon(view.context, PointerIcon.TYPE_HAND) true // Listener consumes the event. }
Java
// Change the icon to a "hand" pointer on hover. // Highlight the view by changing the background. yourView.setOnHoverListener((view, event) -> { addVisualHighlighting(true); view.setPointerIcon( PointerIcon.getSystemIcon(view.getContext(), PointerIcon.TYPE_HAND) ); return true; // Listener consumes the event. });
שתי הדוגמאות הנפוצות ביותר לכך הן:
- שינוי סמל מצביע העכבר כדי להצביע למשתמשים אם לאלמנט יש התנהגות אינטראקטיבית, למשל אם אפשר ללחוץ עליו או לערוך אותו
- הוספת משוב חזותי לפריטים ברשימות או ברשתות גדולות כשהעכבר מרחף מעליהם
גרירה ושחרור
בסביבה עם כמה חלונות, המשתמשים מצפים להיות מסוגלים לגרור ולשחרר פריטים בין אפליקציות. המצב הזה רלוונטי למחשבים שולחניים, לטאבלטים, לטלפונים ולמכשירים מתקפלים במצב מסך מפוצל.
כדאי לשקול אם המשתמשים צפויים לגרור פריטים לאפליקציה. לדוגמה, עורכי תמונות צפויים לקבל תמונות, נגני אודיו צפויים לקבל קובצי אודיו ותוכנות ציור צפויות לקבל תמונות.
כדי להוסיף תמיכה בגרירה ושחרור, אפשר לעיין במאמרים הפעלת גרירה ושחרור , ובפוסט בבלוג Android on ChromeOS — Implementing Drag & Drop.
שיקולים מיוחדים ל-ChromeOS
- חשוב לזכור לבקש הרשאה באמצעות
requestDragAndDropPermissions()
כדי לגשת לפריטים שגוררים מחוץ לאפליקציה כדי שאפשר יהיה לגרור פריט לאפליקציות אחרות, הוא צריך לכלול את הדגל
View.DRAG_FLAG_GLOBAL
.
תמיכה מתקדמת במצביע
אפליקציות שמטפלות באופן מתקדם בקלט של עכבר ולוח מגע צריכות להטמיע את המשתנה המשנה
View#onGenericMotionEvent()
ומשתמשים ב-[MotionEvent.getSource()
][] כדי להבדיל בין SOURCE_MOUSE
לבין SOURCE_TOUCHSCREEN
.
בודקים את האובייקט MotionEvent
כדי להטמיע את ההתנהגות הנדרשת:
- תנועה יוצרת אירועים מסוג
ACTION_HOVER_MOVE
. - לחצנים יוצרים אירועים מסוג
ACTION_BUTTON_PRESS
ו-ACTION_BUTTON_RELEASE
. אפשר גם לבדוק את המצב הנוכחי של כל הלחצנים בעכבר ובמשטח המגע באמצעותgetButtonState()
. - גלילה באמצעות גלגל העכבר יוצרת אירועים מסוג
ACTION_SCROLL
.
שלטים למשחקים
חלק ממכשירי Android עם מסך גדול תומכים בעד ארבעה בקרי משחקים. משתמשים בממשקי ה-API הרגילים של בקרי המשחקים ל-Android כדי לטפל בבקרי משחקים (מידע נוסף זמין במאמר תמיכה בבקרי משחקים).
לחצני בקר המשחקים ממופים לערכים נפוצים לפי מיפוי נפוץ. עם זאת, לא כל יצרני בקרי המשחקים פועלים לפי אותן מוסכמות מיפוי. כדי לספק חוויית שימוש טובה יותר, כדאי לאפשר למשתמשים לבחור מיפויים שונים של בקרי משחק פופולריים. מידע נוסף זמין במאמר עיבוד לחיצות על לחצני בקר המשחקים.
מצב תרגום הקלט
כברירת מחדל, מערכת ChromeOS מפעילה מצב תרגום קלט. במצב הזה, רוב האפליקציות ל-Android פועלות כצפוי בסביבת מחשב. דוגמאות לכך הן הפעלה אוטומטית של גלילה בשני אצבעות בלוח המגע, גלילה באמצעות גלגל העכבר ומיפוי של קואורדינטות תצוגה גולמיות לקווי אורך ורוחב של חלון. בדרך כלל, מפתחי האפליקציות לא צריכים להטמיע אף אחד מההתנהגויות האלה בעצמם.
אם אפליקציה מטמיעה התנהגות קלט מותאמת אישית, למשל הגדרת פעולה מותאמת אישית של צביטה בשתי אצבעות במשטח מגע, או אם תרגומי הקלט האלה לא מספקים את אירועי הקלט שהאפליקציה מצפה להם, אפשר להשבית את מצב תרגום הקלט על ידי הוספת התג הבא למניפסט של Android:
<uses-feature
android:name="android.hardware.type.pc"
android:required="false" />