Compatibilité avec la saisie sur grand écran

Sur les appareils à grand écran, les utilisateurs interagissent souvent avec les applications à l'aide d'un clavier, d'une souris, d'un pavé tactile, d'un stylet ou d'une manette de jeu. Pour autoriser votre application à accepter les entrées provenant d'appareils externes, procédez comme suit:

  • Testez la compatibilité de base avec le clavier, par exemple Ctrl+Z pour annuler, Ctrl+C pour copier et Ctrl+S pour enregistrer. Consultez la section Gérer les actions du clavier pour obtenir la liste des raccourcis clavier par défaut.
  • Testez la prise en charge avancée du clavier, par exemple la navigation au clavier avec la touche Tabulation et les touches fléchées, la confirmation d'entrées de texte avec la touche Entrée, et l'utilisation de la barre d'espace pour lire et mettre en pause le contenu dans les applications multimédias.
  • Testez les interactions de base de la souris, y compris le clic droit pour afficher le menu contextuel, les modifications d'icône au passage de la souris, et l'utilisation de la molette ou du pavé tactile pour faire défiler les événements sur des composants personnalisés.
  • Testez les périphériques d'entrée spécifiques aux applications, comme le stylet, les manettes de jeu et les télécommandes MIDI pour les applications musicales.
  • Envisagez de proposer des modes d'entrée avancés qui permettraient à l'application de se démarquer dans les environnements de bureau (par exemple, le pavé tactile comme fondu enchaîné pour les applications de DJ, la capture de souris pour les jeux et un large éventail de raccourcis clavier).

Clavier

La manière dont votre application réagit à la saisie au clavier contribue à l'expérience utilisateur sur grand écran. Il existe trois types de saisie au clavier : navigation, touches et raccourcis.

La navigation au clavier est rarement implémentée dans les applications centrées sur l'écran tactile, mais les utilisateurs s'y attendent lorsqu'ils utilisent une application et qu'ils ont un clavier à leur disposition. La navigation au clavier peut être essentielle sur les téléphones, les tablettes, les appareils pliables et les ordinateurs pour les utilisateurs ayant des besoins d'accessibilité.

Pour de nombreuses applications, la navigation via les touches fléchées et la touche de tabulation est gérée automatiquement par le framework Android. Par exemple, un Button est sélectionnable par défaut, et la navigation au clavier devrait généralement fonctionner sans code supplémentaire. Pour activer la navigation au clavier pour les vues qui ne sont pas sélectionnables par défaut, marquez-les comme telles, de manière programmatique ou au format XML:

Kotlin

yourView.isFocusable = true

Java

yourView.setFocusable(true);

Vous pouvez également définir l'attribut focusable dans le fichier de mise en page :

android:focusable="true"

Pour en savoir plus, consultez la section Gestion des sélections.

Lorsque la sélection est activée, le framework Android crée un mappage de navigation pour toutes les vues sélectionnables en fonction de leur position. Cela fonctionne généralement normalement. Aucun effort supplémentaire n'est donc nécessaire. Lorsque le mappage par défaut n'est pas adapté aux besoins d'une application, vous pouvez le remplacer comme suit:

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

Testez l'accès à chaque élément d'interface utilisateur de votre application à l'aide du clavier uniquement. Les éléments fréquemment utilisés doivent être accessibles sans utiliser la souris ni la saisie tactile.

N'oubliez pas que le clavier peut être essentiel aux utilisateurs ayant des besoins d'accessibilité spécifiques.

Touches de clavier

Pour la saisie de texte qui serait gérée par un clavier virtuel à l'écran (IME), comme pouret EditText, les applications devraient se comporter comme prévu sur les appareils à grand écran sans nécessiter d'efforts de développement supplémentaires.Pour les touches que le framework ne peut pas anticiper, les applications doivent gérer ce comportement elles-mêmes. Cela est particulièrement vrai pour les applications avec des vues personnalisées.

Il peut s'agir d'applications de chat qui utilisent la touche Entrée pour envoyer un message, d'applications multimédias qui lancent et arrêtent la lecture avec la barre d'espace, ou de jeux qui contrôlent le mouvement avec les touches w, a, s et d.

La plupart des applications ignorent le rappel onKeyUp() et ajoutent le comportement attendu pour chaque code clavier reçu:

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

Un événement onKeyUp se produit lorsqu'une touche est relâchée. L'utilisation du rappel évite aux applications de devoir traiter plusieurs événements onKeyDown si une touche est maintenue enfoncée ou si elle est libérée lentement. Les jeux et les applications qui doivent détecter le moment où une touche est enfoncée ou si l'utilisateur maintient une touche enfoncée peuvent écouter l'événement onKeyDown et gérer eux-mêmes les événements onKeyDown répétés.

Pour en savoir plus, consultez Gérer les actions du clavier.

Raccourcis

Les raccourcis clavier courants qui incluent les touches Ctrl, Alt, Maj et Meta sont attendus lorsque vous utilisez un clavier physique. Si une application n'implémente pas de raccourcis, l'expérience peut être frustrante pour les utilisateurs. Les utilisateurs avancés apprécient également les raccourcis pour les tâches fréquentes spécifiques aux applications. Les raccourcis contribuent à la facilité d'utilisation d'une application et la différencient de celles qui n'en ont pas.

Les raccourcis les plus courants sont Ctrl+S (Enregistrer), Ctrl+Z (Annuler) et Ctrl+Maj+Z (Répéter). Pour obtenir la liste des raccourcis par défaut, consultez Gérer les actions du clavier.

Les raccourcis peuvent être activés en implémentant dispatchKeyShortcutEvent() pour intercepter toutes les combinaisons de touches (Alt, Ctrl, Maj et Meta) pour un code clavier donné. Pour vérifier si une touche de modification spécifique est utilisée, utilisez:

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

La séparation du code de raccourci des autres méthodes de saisie au clavier (onKeyUp() et onKeyDown(), par exemple) accepte les touches de modification par défaut sans avoir à implémenter manuellement les vérifications des touches de modification dans tous les cas. L'autorisation de toutes les combinaisons de touches de modification peut également être plus pratique pour les utilisateurs habitués à différentes configurations de clavier et systèmes d'exploitation.

Toutefois, vous pouvez également implémenter des raccourcis dans onKeyUp() en recherchant KeyEvent.isCtrlPressed(), KeyEvent.isShiftPressed() ou KeyEvent.isAltPressed(). Cette approche est parfois plus facile à gérer si le comportement de la touche modifié correspond davantage à une modification d'un comportement d'application qu'à un raccourci. (par exemple, dans les jeux, lorsque W signifie "avancer en marchant" et Maj+W signifie "avancer en courant").

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

Consultez également l'Outil d'aide pour les raccourcis clavier.

Stylet

De nombreux appareils à grand écran sont livrés avec un stylet. Les applications Android gèrent les stylets comme la saisie tactile. Certains appareils peuvent également disposer d'une table de dessin USB ou Bluetooth, comme Wacom Intuos. Les applications Android peuvent recevoir une entrée Bluetooth, mais pas une entrée USB.

Un événement de stylet est signalé comme événement tactile par View#onTouchEvent() ou View#onGenericMotionEvent(), et contient un objet MotionEvent#getSource() de type SOURCE_STYLUS.

L'objet MotionEvent contient des informations sur l'événement:

Points historiques

Android regroupe les événements d'entrée et les distribue une fois par frame. Un stylet peut signaler des événements avec une fréquence beaucoup plus élevée que l'écran. Lorsque vous créez des applications de dessin, recherchez les événements récents à l'aide des API getHistorical:

Refus de la paume de la main

Lorsque les utilisateurs dessinent, écrivent ou interagissent avec votre application à l'aide d'un stylet, ils touchent parfois l'écran avec la paume de leur main. L'événement tactile (défini sur ACTION_DOWN ou ACTION_POINTER_DOWN) peut être signalé à votre application avant que le système ne le reconnaisse et n'ignore la pression involontaire via la paume de la main.

Android annule les événements tactiles de la paume de la main en envoyant un MotionEvent. Si votre application reçoit ACTION_CANCEL, annulez le geste. Si votre application reçoit une erreur ACTION_POINTER_UP, vérifiez si FLAG_CANCELED est défini. Si c'est le cas, annulez le geste.

Ne recherchez pas uniquement FLAG_CANCELED. Sur Android 13 (niveau d'API 33) ou version ultérieure, le système définit FLAG_CANCELED pour les événements ACTION_CANCEL, mais il ne définit pas l'indicateur sur les versions Android antérieures.

Android 12

Sur Android 12 (niveau d'API 32) et versions antérieures, la détection du refus de la paume de la main n'est possible que pour les événements tactiles à un seul pointeur. Si une pression via la paume de la main est le seul pointeur, le système annule l'événement en définissant ACTION_CANCEL sur l'objet d'événement de mouvement. Si les autres pointeurs impliquent une pression, le système définit ACTION_POINTER_UP, ce qui est insuffisant pour détecter le refus de la paume de la main.

Android 13

Sur Android 13 (niveau d'API 33) ou version ultérieure, si une pression via la paume de la main est le seul pointeur, le système annule l'événement en définissant ACTION_CANCEL et FLAG_CANCELED sur l'objet d'événement de mouvement. Si les autres pointeurs impliquent une pression, le système définit ACTION_POINTER_UP et FLAG_CANCELED.

Chaque fois que votre application reçoit un événement de mouvement avec ACTION_POINTER_UP, recherchez FLAG_CANCELED pour déterminer si l'événement indique un refus de la paume de la main (ou une autre annulation d'événement).

Applications de prise de notes

ChromeOS utilise un intent spécial qui présente aux utilisateurs les applications de prise de notes enregistrées en tant que telles. Pour enregistrer une application en tant qu'application de prise de notes, ajoutez le code suivant à votre fichier manifeste d'application:

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

Lorsqu'une application est enregistrée auprès du système, l'utilisateur peut la sélectionner comme application de prise de notes par défaut. Lorsqu'une nouvelle note est demandée, l'application doit créer une note vide prête à être saisie par le stylet. Lorsque l'utilisateur souhaite annoter une image (par exemple, une capture d'écran ou une image téléchargée), l'application se lance avec ClipData et contient un ou plusieurs éléments avec des URI content://. L'application doit créer une note qui utilise la première image jointe comme image d'arrière-plan et passer dans un mode permettant à l'utilisateur de dessiner à l'écran avec un stylet.

Tester les intents de prise de notes sans stylet

[TBD remove section.]

Pour vérifier si une application répond correctement aux intents de prise de notes sans stylet actif, utilisez la méthode suivante afin d'afficher les options de prise de notes sur ChromeOS:

  1. Activez le mode développeur et rendez l'appareil accessible en écriture.
  2. Appuyez sur Ctrl+Alt+F2 pour ouvrir un terminal.
  3. Exécutez la commande sudo vi /etc/chrome_dev.conf.
  4. Appuyez sur i pour effectuer des modifications, puis ajoutez --ash-enable-palette à une nouvelle ligne à la fin du fichier
  5. Pour enregistrer, appuyez sur Échap, puis saisissez :, w, q et appuyez sur Entrée.
  6. Appuyez sur Ctrl+Alt+F1 pour revenir à l'interface utilisateur ChromeOS standard.
  7. Déconnectez-vous, puis reconnectez-vous.

Un menu de stylet devrait maintenant s'afficher sur l'étagère:

  • Appuyez sur le bouton du stylet situé sur l'étagère, puis sélectionnez Nouvelle note. Une note de dessin vide devrait s'afficher.
  • Prenez une capture d'écran. À partir de l'étagère, sélectionnez Bouton du stylet > Capturer l'écran ou téléchargez une image. L'option Annoter l'image devrait s'afficher dans la notification. Celle-ci devrait lancer l'application avec l'image prête à être annotée.

Compatibilité avec la souris et le pavé tactile

La plupart des applications ne doivent généralement gérer que trois événements axés sur les grands écrans : effectuer un clic droit, pointer le curseur et glisser-déposer.

Effectuer un clic droit

Toutes les actions qui entraînent l'affichage d'un menu contextuel par une application, comme l'appui prolongé sur un élément de la liste, doivent également réagir aux événements de clic droit.

Pour gérer les événements de clic droit, les applications doivent enregistrer un élément View.OnContextClickListener:

Kotlin

yourView.setOnContextClickListener {
    showContextMenu()
    true
}

Java

yourView.setOnContextClickListener(v -> {
    showContextMenu();
    return true;
});

Pour découvrir comment créer des menus contextuels, consultez Créer un menu contextuel.

Survol

Vous pouvez rendre vos mises en page d'application plus fluides et plus faciles à utiliser en gérant les événements de pointage. C'est particulièrement vrai pour les composants vues:

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

Voici les deux exemples les plus courants:

  • Modifier l'icône du pointeur de la souris pour indiquer aux utilisateurs si un élément a un comportement interactif, par exemple s'il est cliquable ou modifiable
  • Ajouter un retour visuel aux éléments d'une longue liste ou grille lorsque le pointeur passe dessus

Glisser-déposer

Dans un environnement multifenêtre, les utilisateurs s'attendent à pouvoir glisser-déposer des éléments entre les applications. Cela est le cas pour les ordinateurs, les tablettes, les téléphones et les pliables en mode écran partagé.

Déterminez si les utilisateurs sont susceptibles de faire glisser des éléments dans votre application. Par exemple, les éditeurs de photos doivent s'attendre à recevoir des photos, les lecteurs audio à recevoir des fichiers audio et les programmes de dessin à recevoir des photos.

Pour permettre de glisser-déposer des éléments, consultez les pages Activer le glisser-déposer ainsi que l'article de blog Android sur ChromeOS : implémenter le glisser-déposer.

Remarques concernant ChromeOS

  • N'oubliez pas de demander l'autorisation avec requestDragAndDropPermissions() pour accéder aux éléments que l'utilisateur fait glisser depuis l'extérieur de l'application.
  • Un élément doit être associé à l'indicateur View.DRAG_FLAG_GLOBAL pour pouvoir être glissé vers d'autres applications.

Compatibilité avancée avec les pointeurs

Les applications qui gèrent les commandes avancées de la souris et du pavé tactile doivent implémenter un modificateur View#onGenericMotionEvent() et utilisez [MotionEvent.getSource()][] pour distinguer SOURCE_MOUSE et SOURCE_TOUCHSCREEN.

Examinez l'objet MotionEvent pour mettre en œuvre le comportement requis:

  • Le mouvement génère des événements ACTION_HOVER_MOVE.
  • Les boutons génèrent des événements ACTION_BUTTON_PRESS et ACTION_BUTTON_RELEASE. Vous pouvez également vérifier l'état actuel de tous les boutons de la souris et du pavé tactile avec getButtonState().
  • Le défilement de la molette de la souris génère des événements ACTION_SCROLL.

Manettes de jeu

Certains appareils Android à grand écran acceptent jusqu'à quatre manettes de jeu. Utilisez les API de manette de jeu Android standards pour gérer les manettes de jeu (consultez Prendre en charge les manettes de jeu).

Les boutons de la manette de jeu sont mis en correspondance avec des valeurs communes suivant un mappage commun. Cependant, tous les fabricants de manettes de jeu ne suivent pas les mêmes conventions de mappage. Vous offrirez une bien meilleure expérience si vous autorisez les utilisateurs à sélectionner différents mappages de manettes populaires. Pour en savoir plus, consultez la section Traiter les pressions sur les boutons d'une manette de jeu.

Mode de conversion d'entrée

ChromeOS offre un mode de conversion d'entrée par défaut. Pour la plupart des applications Android, ce mode permet aux applications de fonctionner comme prévu dans un environnement de bureau. Par exemple, il permet l'activation automatique du défilement à deux doigts sur le pavé tactile, le défilement de la molette de la souris et le mappage des coordonnées brutes de l'écran avec les coordonnées de la fenêtre. En règle générale, les développeurs d'applications n'ont pas besoin d'implémenter ces comportements eux-mêmes.

Si une application met en œuvre un comportement de saisie personnalisé, par exemple si vous définissez une action personnalisée de pincement avec deux doigts sur le pavé tactile, ou si ces conversions d'entrée ne fournissent pas les événements d'entrée attendus par l'application, vous pouvez désactiver la conversion d'entrée en ajoutant la balise suivante au fichier manifeste Android:

<uses-feature
    android:name="android.hardware.type.pc"
    android:required="false" />

Ressources supplémentaires