תאימות קלט במסכים גדולים

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

  • בודקים את התמיכה הבסיסית במקלדת, כמו Ctrl+Z לביטול פעולה, Ctrl+C להעתקה ו-Ctrl+S לשמירה. במאמר טיפול בפעולות במקלדת מפורטת רשימה של מקשי הקיצור שמוגדרים כברירת מחדל.
  • בודקים את התמיכה המתקדמת במקלדת, למשל ניווט באמצעות המקשים Tab ו החצים, אישור הזנת טקסט באמצעות המקש Enter, והפעלה והשהיה באמצעות מקש הרווח באפליקציות מדיה.
  • בודקים אינטראקציות בסיסיות עם העכבר, כולל לחיצה ימנית לפתיחת תפריט ההקשר, שינויים בסמל כשמציבים מעליו את הסמן ואירועי גלילה באמצעות גלגל העכבר או משטח המגע ברכיבים בהתאמה אישית.
  • בודקים מכשירים לקליטת נתונים שספציפיים לאפליקציה, כמו סטיילוס, שלטי משחק ובקרי MIDI של אפליקציות מוזיקה.
  • שקלו להוסיף תמיכה בקלט מתקדם שיכולה להבליט את האפליקציה בסביבות של מחשבים, למשל: לוח מגע כ-cross-fader לאפליקציות של תקליטנים, לכידת עכבר למשחקים ומקשי קיצור למשתמשים שמעדיפים להשתמש במקלדת.

מקלדת

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

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

באפליקציות רבות, הניווט באמצעות מקשי החצים ומקש Tab מטופל באופן אוטומטי על ידי Android framework. לדוגמה, אפשר להתמקד ב-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

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

מידע נוסף זמין במאמר טיפול בפעולות במקלדת.

קיצורי דרך

כשמשתמשים במקלדת פיזית, אפשר להשתמש במקשי הקיצור הנפוצים שכוללים את המקשים Ctrl,‏ Alt, ‏ Shift ו-Meta. אם באפליקציה אין מקשי קיצור, חוויית המשתמש עלולה להיות מתסכלת. משתמשים מתקדמים גם מעריכים קיצורי דרך למשימות ספציפיות לאפליקציה שמשתמשים בהן לעיתים קרובות. קיצורי דרך מקלים על השימוש באפליקציה ומבדילים אותה מאפליקציות שאין בהן קיצורי דרך.

מקשי קיצור נפוצים: Ctrl+S (שמירה), Ctrl+Z (ביטול הפעולה האחרונה) ו-Ctrl+Shift+Z (ביצוע מחדש). במאמר הזה מפורטת רשימה של מקשי הקיצור שמוגדרים כברירת מחדל.

כדי להפעיל מקשי קיצור, אפשר להטמיע את dispatchKeyShortcutEvent() כדי ליירט את כל שילובי המקשים (Alt, ‏ Ctrl, ‏ Shift ו-Meta) של קוד מקש נתון. כדי לבדוק אם מקש צירוף ספציפי נלחץ, משתמשים ב:

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);
}

אפשר לעיין גם בכלי העזר למקשי הקיצור.

סטיילוס

הרבה מכשירים עם מסך גדול מגיעים עם סטיילוס. אפליקציות ל-Android מתייחסות לסטיילוסים כקלט של מסך מגע. בחלק מהמכשירים יכול להיות גם לוח ציור עם חיבור USB או Bluetooth, כמו Wacom Intuos. אפליקציות ל-Android יכולות לקבל קלט מ-Bluetooth אבל לא מ-USB.

אירוע של סטיילוס מדווח כאירוע של מסך מגע על ידי View#onTouchEvent() או View#onGenericMotionEvent(), והוא מכיל MotionEvent#getSource() מסוג SOURCE_STYLUS.

האובייקט MotionEvent מכיל מידע על האירוע:

נקודות היסטוריות

מערכת Android אוספת אירועי קלט ושולחת אותם פעם אחת בכל פריים. סטיילוס יכול לדווח על אירועים בתדירות גבוהה בהרבה מהתצוגה. כשיוצרים אפליקציות ציור, צריך לבדוק אם יש אירועים שהתרחשו לאחרונה באמצעות ממשקי ה-API של getHistorical:

התעלמות מנגיעות של כף היד

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

<intent-filter>
    <action android:name="org.chromium.arc.intent.action.CREATE_NOTE" />
    <category android:name="android.intent.category.DEFAULT" />
</intent-filter>

כשאפליקציה רשומה במערכת, המשתמש יכול לבחור אותה כאפליקציית ברירת המחדל לכתיבת הערות. כשמבקשים הערה חדשה, האפליקציה צריכה ליצור הערה ריקה שמוכנה לקלט מסטיילוס. כשהמשתמש רוצה להוסיף הערות לתמונה (כמו צילום מסך או תמונה שהורדה), האפליקציה מופעלת עם ClipData שמכיל פריט אחד או יותר עם מזהי URI של content://. האפליקציה צריכה ליצור פתק שמשתמש בתמונה המצורפת הראשונה כתמונת רקע, ולהיכנס למצב שבו המשתמש יכול לצייר על המסך באמצעות סטיילוס.

בדיקת Intent של כתיבת הערות בלי סטיילוס

כדי לבדוק אם אפליקציה מגיבה בצורה נכונה ל-intent של כתיבת פתקים בלי סטיילוס פעיל, משתמשים בשיטה הבאה כדי להציג את האפשרויות לכתיבת פתקים ב-ChromeOS:

  1. עוברים למצב פיתוח ומאפשרים כתיבה במכשיר
  2. מקישים על Ctrl+Alt+F2 כדי לפתוח טרמינל.
  3. מריצים את הפקודה sudo vi /etc/chrome_dev.conf
  4. מקישים על i כדי לערוך ומוסיפים את --ash-enable-palette לשורה חדשה בסוף הקובץ.
  5. כדי לשמור, מקישים על Esc, מקלידים :, w, q ומקישים על Enter.
  6. מקישים על Ctrl+Alt+F1 כדי לחזור לממשק המשתמש הרגיל של ChromeOS.
  7. יוצאים מהחשבון ונכנסים אליו שוב

תפריט סטיילוס אמור להופיע עכשיו במדף:

  • לוחצים על כפתור הסטיילוס במדף ובוחרים באפשרות הערה חדשה. ייפתח פתק ריק לציור.
  • מצלמים את המסך. במדף, לוחצים על כפתור הסטיילוס > צילום מסך או מורידים תמונה. בהתראה אמורה להופיע האפשרות הוספת הערות לתמונה. האפליקציה אמורה להיפתח עם התמונה שמוכנה להוספת הערות.

תמיכה בעכבר ובלוח מגע

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

לחיצה ימנית

כל פעולה שגורמת לאפליקציה להציג תפריט הקשר, כמו לחיצה ארוכה על פריט ברשימה, צריכה להגיב גם לאירועים מסוג קליק של לחיצה ימנית.

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

שיקולים מיוחדים לגבי 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" />

מקורות מידע נוספים