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

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

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

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 מכיל מידע על האירוע:

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

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

דחייה של 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:

  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 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" />

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