Les documents suivants sont destinés aux développeurs d'applications.
Pour que votre application soit compatible avec le dispositif rotatif, vous DEVEZ:
- Placez un
FocusParkingView
dans la mise en page de l'activité correspondante. - Assurez-vous que les vues sont (ou ne sont pas) sélectionnables.
- Utilisez des
FocusArea
pour encapsuler toutes les vues sélectionnables, à l'exception desFocusParkingView
Chacune de ces tâches est détaillée ci-dessous, une fois que vous avez configuré votre environnement pour développer des applications compatibles avec un dispositif rotatif.
Configurer un contrôleur rotatif
Avant de pouvoir développer des applications compatibles avec un dispositif rotatif, vous avez besoin d'un contrôleur rotatif ou un remplaçant. Vous disposez des options décrites ci-dessous.
Émulateur
source build/envsetup.sh && lunch car_x86_64-userdebug m -j emulator -wipe-data -no-snapshot -writable-system
Vous pouvez également utiliser aosp_car_x86_64-userdebug
.
Pour accéder au contrôleur rotatif émulé, procédez comme suit:
- Appuyez sur les trois points au bas de la barre d'outils:
- Sélectionnez Car rotary (Rotaire de la voiture) dans la fenêtre des commandes avancées:
<ph type="x-smartling-placeholder">
Clavier USB
- Branchez un clavier USB à votre appareil qui exécute Android Automotive OS (AAOS). Dans certains cas, cela empêche le clavier à l'écran d'apparaître.
- Utilisez un build
userdebug
oueng
. - Activez le filtrage des événements clés:
adb shell settings put secure android.car.ROTARY_KEY_EVENT_FILTER 1
- Consultez le tableau ci-dessous pour trouver la clé correspondant à chaque action:
Clé Action par dispositif rotatif Q Faire pivoter dans le sens inverse des aiguilles d'une montre E Faire pivoter dans le sens des aiguilles d'une montre A Déplacer vers la gauche D Déplacer vers la droite W Déplacer vers le haut S Déplacer vers le bas F ou virgule Bouton central R ou Échap Bouton Retour
Commandes ADB
Vous pouvez utiliser les commandes car_service
pour injecter des événements de saisie par dispositif rotatif. Ces commandes
peut s'exécuter sur des appareils équipés d'Android Automotive OS (AAOS) ou sur un émulateur.
Commandes car_service | Saisie par dispositif rotatif |
---|---|
adb shell cmd car_service inject-rotary |
Faire pivoter dans le sens inverse des aiguilles d'une montre |
adb shell cmd car_service inject-rotary -c true |
Faire pivoter dans le sens des aiguilles d'une montre |
adb shell cmd car_service inject-rotary -dt 100 50 |
Faire pivoter plusieurs fois dans le sens inverse des aiguilles d'une montre (il y a 100 ms et 50 ms avant) |
adb shell cmd car_service inject-key 282 |
Déplacer vers la gauche |
adb shell cmd car_service inject-key 283 |
Déplacer vers la droite |
adb shell cmd car_service inject-key 280 |
Déplacer vers le haut |
adb shell cmd car_service inject-key 281 |
Déplacer vers le bas |
adb shell cmd car_service inject-key 23 |
Clic sur le bouton central |
adb shell input keyevent inject-key 4 |
Clic sur le bouton Retour |
Contrôleur rotatif OEM
Lorsque le matériel du contrôleur rotatif est opérationnel, réaliste. Elle est particulièrement utile pour tester la rotation rapide.
FocusParkingView
FocusParkingView
est une vue transparente dans la
Bibliothèque Car UI (car-ui-library).
RotaryService
l'utilise pour prendre en charge la navigation avec le contrôleur rotatif.
FocusParkingView
doit être la première vue sélectionnable
dans la mise en page. Il doit être placé en dehors de tous les éléments FocusArea
. Chaque fenêtre doit en comporter une
FocusParkingView
Si vous utilisez déjà la mise en page
car-ui-library de base,
qui contient un FocusParkingView
, vous n'avez pas besoin d'en ajouter un autre
FocusParkingView
Vous trouverez ci-dessous un exemple de FocusParkingView
dans
RotaryPlayground
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <com.android.car.ui.FocusParkingView android:layout_width="wrap_content" android:layout_height="wrap_content"/> <FrameLayout android:layout_width="match_parent" android:layout_height="match_parent"/> </FrameLayout>
Voici les raisons pour lesquelles vous avez besoin d'une FocusParkingView
:
- Android n'efface pas automatiquement le curseur lorsqu'il est sélectionné dans une autre fenêtre. Si vous
lorsque le curseur est désélectionné dans la fenêtre précédente, Android recentre une vue dans cette fenêtre, ce qui
entraîne le focus de deux fenêtres simultanément. Ajouter un
FocusParkingView
à chaque fenêtre peut résoudre ce problème. Cette vue est transparente et la mise en surbrillance par défaut est désactivé, de sorte qu'il soit invisible à l'utilisateur, qu'il soit sélectionné ou non. Elle peut activer le focus de sorte queRotaryService
puisse y placer le focus. pour supprimer la mise en surbrillance. - S'il n'y a qu'un seul
FocusArea
dans la fenêtre actuelle, rotation du contrôleur dansFocusArea
amèneRotaryService
à déplacer le curseur de la vue de droite vers la vue de gauche (et vice versa). Ajout de cette vue... à chaque fenêtre peut résoudre le problème. LorsqueRotaryService
détermine le focus cible est unFocusParkingView
, il peut déterminer qu'une enveloppe est sur le point se produit et, à ce stade, elle évite le contouring en ne déplaçant pas la mise au point. - Lorsque le contrôleur rotatif lance une application, Android sélectionne la première vue sélectionnable,
qui est toujours
FocusParkingView
.FocusParkingView
détermine la vue optimale sur laquelle effectuer le focus, puis applique la mise au point.
Vues sélectionnables
RotaryService
s'appuie sur le framework
existants
le concept de focalisation sur l'écran, remontant à l'époque où les téléphones avaient des claviers physiques et des pavés directionnels.
L'attribut android:nextFocusForward
existant a été redéfini pour le dispositif rotatif.
(voir Personnalisation de l'élément FocusArea), mais
android:nextFocusLeft
, android:nextFocusRight
,
android:nextFocusUp
et android:nextFocusDown
ne le sont pas.
RotaryService
se concentre uniquement sur les vues sélectionnables. Quelques vues,
comme les Button
,
sont généralement sélectionnables. D'autres, comme les TextView
et les ViewGroup
,
ne le sont généralement pas. Les vues cliquables sont automatiquement sélectionnables
cliquables lorsqu'ils disposent d'un écouteur de clics. Si cette logique automatique permet d'obtenir
vous n'avez pas besoin de la définir explicitement. Si la logique automatique ne
obtenir la mise au point souhaitée, définissez l'attribut android:focusable
sur
true
ou false
, ou définissez par programmation la sélection de la vue avec
View.setFocusable(boolean)
Pour que RotaryService
puisse se concentrer dessus, une vue DOIT
doivent remplir les conditions suivantes:
- Sélectionnable
- Activé
- Visible
- avoir des valeurs non nulles pour la largeur et la hauteur ;
Si une vue ne remplit pas toutes ces conditions (par exemple, un bouton sélectionnable, mais désactivé),
l'utilisateur ne peut pas utiliser le
contrôle rotatif pour effectuer le focus dessus. Si vous souhaitez privilégier les vues désactivées,
envisagez d'utiliser un état personnalisé plutôt que android:state_enabled
pour contrôler
la vue s'affiche sans indiquer qu'Android doit la considérer comme désactivée. Votre application peut informer
pourquoi la vue est désactivée lorsqu'il appuie dessus. La section suivante explique comment procéder.
État personnalisé
Pour ajouter un état personnalisé:
- Ajouter un attribut personnalisé
à votre vue. Par exemple, pour ajouter un état personnalisé
state_rotary_enabled
au Classe de vueCustomView
, utilisez:<declare-styleable name="CustomView"> <attr name="state_rotary_enabled" format="boolean" /> </declare-styleable>
- Pour suivre cet état, ajoutez une variable d'instance à votre vue, ainsi que des méthodes d'accesseur:
private boolean mRotaryEnabled; public boolean getRotaryEnabled() { return mRotaryEnabled; } public void setRotaryEnabled(boolean rotaryEnabled) { mRotaryEnabled = rotaryEnabled; }
- Pour lire la valeur de votre attribut lors de la création de la vue:
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CustomView); mRotaryEnabled = a.getBoolean(R.styleable.CustomView_state_rotary_enabled);
- Dans votre classe de vue, remplacez la méthode
onCreateDrawableState()
, puis ajouter l'état personnalisé, le cas échéant. Par exemple:@Override protected int[] onCreateDrawableState(int extraSpace) { if (mRotaryEnabled) extraSpace++; int[] drawableState = super.onCreateDrawableState(extraSpace); if (mRotaryEnabled) { mergeDrawableStates(drawableState, { R.attr.state_rotary_enabled }); } return drawableState; }
- Faites en sorte que le gestionnaire de clics de votre vue fonctionne différemment en fonction de son état. Par exemple,
le gestionnaire de clics risque de ne rien faire ou d'afficher un toast lorsque
mRotaryEnabled
estfalse
. - Pour que le bouton apparaisse désactivé, utilisez le drawable d'arrière-plan de votre vue
app:state_rotary_enabled
au lieu deandroid:state_enabled
. Si vous ne l'avez pas encore fait, vous devrez ajouter:xmlns:app="http://schemas.android.com/apk/res-auto"
- Si votre vue est désactivée dans l'une des mises en page, remplacez
android:enabled="false"
parapp:state_rotary_enabled="false"
, puis ajoutez l'espace de nomsapp
. comme indiqué ci-dessus. - Si votre vue est désactivée de manière programmatique, remplacez les appels à
setEnabled()
. avec des appels àsetRotaryEnabled()
.
Zone ciblée
Utilisez FocusAreas
pour partitionner les vues sélectionnables en blocs afin de faciliter la navigation.
plus facile et d’être cohérent
avec les autres applications. Par exemple, si votre application dispose d'une barre d'outils, celle-ci
doit se trouver dans un FocusArea
distinct du reste de votre application. Barres d'onglets et
les autres éléments de navigation doivent également être séparés du reste de l'application. Listes volumineuses
doivent généralement avoir leur propre FocusArea
. Si ce n'est pas le cas, ils doivent alterner
toute la liste pour accéder
à certaines vues.
FocusArea
est une sous-classe de LinearLayout
dans la bibliothèque car-ui-library.
Lorsque cette fonctionnalité est activée, FocusArea
trace une mise en surbrillance lorsque l'une de ses
descendants est ciblé. Pour en savoir plus, consultez
Personnalisation de la sélection de mise en surbrillance :
Lors de la création d'un bloc de navigation dans le fichier de mise en page, si vous prévoyez d'utiliser un
LinearLayout
en tant que conteneur pour ce bloc, utilisez plutôt FocusArea
.
Sinon, encapsulez le bloc dans une FocusArea
.
N'imbriquez PAS un FocusArea
dans un autre FocusArea
.
Cela entraîne un comportement de navigation non défini. Assurez-vous que toutes les vues sélectionnables sont
imbriquées dans une FocusArea
.
Un exemple de FocusArea
dans
RotaryPlayground
est affiché ci-dessous:
<com.android.car.ui.FocusArea android:layout_margin="16dp" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <EditText android:layout_width="match_parent" android:layout_height="wrap_content" android:singleLine="true"> </EditText> </com.android.car.ui.FocusArea>
FocusArea
fonctionne comme suit:
- Lors de la gestion des actions de rotation et de déplacement,
RotaryService
recherche des instances deFocusArea
dans la hiérarchie des vues. - Lors de la réception d'un événement de rotation,
RotaryService
déplace le curseur vers un autre Vue pouvant être sélectionnée dans le mêmeFocusArea
. - Lors de la réception d'un événement de rappel,
RotaryService
déplace le curseur vers une autre vue qui peut s'activer dans un autre élémentFocusArea
(généralement adjacent)
Si vous n'incluez aucun FocusAreas
dans votre mise en page, la vue racine est traitée
en tant que zone d'action implicite. L'utilisateur ne parvient pas à naviguer dans l'application. Au lieu de cela, ils
faire pivoter toutes les vues sélectionnables, ce qui peut convenir pour les boîtes de dialogue.
Personnalisation de FocusArea
Vous pouvez utiliser deux attributs d'affichage standards pour personnaliser la navigation par dispositif rotatif:
android:nextFocusForward
permet aux développeurs d'applications de spécifier la rotation dans un domaine donné. Il s'agit du même attribut utilisé pour contrôler l'ordre de tabulation pour la navigation au clavier. N'utilisez PAS cet attribut pour créer une boucle. Utilisez plutôtapp:wrapAround
(voir ci-dessous) pour créer une boucle.android:focusedByDefault
permet aux développeurs d'applications de spécifier le par défaut dans la fenêtre. N'utilisez PAS cet attribut.app:defaultFocus
(voir ci-dessous) dans le mêmeFocusArea
.
FocusArea
définit également certains attributs pour personnaliser la navigation par dispositif rotatif.
Ces attributs ne permettent pas de personnaliser des zones d'action implicites.
- (Android 11 QPR3, Android 11 Car,
Android 12)
app:defaultFocus
permet de spécifier l'ID d'une vue descendante sélectionnable, à mettre en évidence lorsque l'utilisateur rappels automatiques concernant ceFocusArea
. - (Android 11 QPR3, Android 11 Car,
Android 12)
app:defaultFocusOverridesHistory
peut être définie surtrue
pour que la vue spécifiée ci-dessus soit mise en évidence, même si avec pour indiquer qu'une autre vue de ceFocusArea
était sélectionnée. - (Android 12)
Utiliserapp:nudgeLeftShortcut
,app:nudgeRightShortcut
,app:nudgeUpShortcut
etapp:nudgeDownShortcut
pour spécifier l'ID d'une vue descendante sélectionnable, à mettre en surbrillance lorsque la des encouragements de l’utilisateur dans une direction donnée. Pour en savoir plus, consultez le contenu de raccourcis rapides ci-dessous.(Android 11 QPR3, Android 11 Car, obsolète dans Android 12)
app:nudgeShortcut
etapp:nudgeShortcutDirection
n'acceptaient qu'un seul raccourci de rappel automatique. - (Android 11 QPR3, Android 11 Car,
Android 12)
Pour activer la rotation afin d'encapsuler leFocusArea
,app:wrapAround
peut être défini surtrue
. Cette méthode est généralement utilisée lorsque les vues sont organisées cercle ou ovale. - (Android 11 QPR3, Android 11 Car,
Android 12)
Pour ajuster la marge intérieure de la mise en surbrillance dans ceFocusArea
, utilisezapp:highlightPaddingStart
,app:highlightPaddingEnd
,app:highlightPaddingTop
,app:highlightPaddingBottom
,app:highlightPaddingHorizontal
etapp:highlightPaddingVertical
. - (Android 11 QPR3, Android 11 Car,
Android 12)
Pour ajuster les limites perçues de ceFocusArea
afin de trouver une cible de rappel, utiliserapp:startBoundOffset
,app:endBoundOffset
,app:topBoundOffset
,app:bottomBoundOffset
,app:horizontalBoundOffset
etapp:verticalBoundOffset
. - (Android 11 QPR3, Android 11 Car,
Android 12)
Pour spécifier explicitement l'identifiantFocusArea
(ou zones) adjacentes dans un itinéraire donné, utilisezapp:nudgeLeft
,app:nudgeRight
,app:nudgeUp
etapp:nudgeDown
Utilisez cette option lorsque la recherche géométrique utilisée par défaut n'a pas trouvé la cible souhaitée.
Les rappels automatiques permettent généralement de passer d'une section FocusAreas à une autre. Mais avec les
raccourcis de rappel,
parfois d'abord naviguer dans un FocusArea
afin que l'utilisateur puisse avoir besoin
pour basculer deux fois vers l'élément FocusArea
suivant. Les raccourcis de type "Décaler" sont utiles
Lorsqu'un FocusArea
contient une longue liste suivie d'un
Bouton d'action flottant,
comme dans l'exemple ci-dessous:
Sans le raccourci de rappel automatique, l'utilisateur devrait faire défiler la liste entière pour atteindre le bouton d'action flottant.
Sélectionner la personnalisation de la sélection
Comme indiqué ci-dessus, RotaryService
s'appuie sur le concept existant de
sélection d'affichage. Lorsque l'utilisateur effectue une rotation et des encouragements, RotaryService
déplace le curseur,
une vue et une autre. Dans Android, lorsqu'une vue est sélectionnée, si elle:
- A défini sa propre mise en surbrillance du curseur, Android la dessine dans la vue.
- Ne spécifie pas de mise en surbrillance du curseur et celle par défaut n'est pas désactivée, Android affiche la mise en surbrillance par défaut de la vue.
En général, les applications conçues pour l'écran tactile n'affichent pas les zones de surbrillance appropriées.
La mise en surbrillance par défaut est fournie par le framework Android et peut être remplacée
par l'OEM. Les développeurs d'applications la reçoivent lorsque le thème qu'ils utilisent est dérivé de
Theme.DeviceDefault
Pour une expérience utilisateur cohérente, utilisez autant que possible la mise en surbrillance par défaut.
Si vous avez besoin d'une mise en surbrillance personnalisée (par exemple, ronde ou en forme de pilule), ou si vous
à l'aide d'un thème non dérivé de Theme.DeviceDefault
, utilisez la bibliothèque car-ui-library.
pour spécifier votre propre mise en surbrillance pour chaque vue.
Pour spécifier une mise en surbrillance personnalisée d'une vue, modifiez le drawable d'arrière-plan ou de premier plan de la vue en un drawable qui diffère lorsque la vue est sélectionnée. En général, vous devez remplacer en arrière-plan. Le drawable suivant, s'il est utilisé comme arrière-plan d'une vue carrée, produit une mise en surbrillance circulaire:
<selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_focused="true" android:state_pressed="true"> <shape android:shape="oval"> <solid android:color="@color/car_ui_rotary_focus_pressed_fill_color"/> <stroke android:width="@dimen/car_ui_rotary_focus_pressed_stroke_width" android:color="@color/car_ui_rotary_focus_pressed_stroke_color"/> </shape> </item> <item android:state_focused="true"> <shape android:shape="oval"> <solid android:color="@color/car_ui_rotary_focus_fill_color"/> <stroke android:width="@dimen/car_ui_rotary_focus_stroke_width" android:color="@color/car_ui_rotary_focus_stroke_color"/> </shape> </item> <item> <ripple...> ... </ripple> </item> </selector>
(Android 11 QPR3, Android 11 Car, Android 12) Bold (Références de ressources en gras) dans l'exemple ci-dessus, pour identifier les ressources définies par la bibliothèque car-ui-library. L'OEM les remplace par des valeurs cohérentes avec la mise en surbrillance par défaut qu'elles spécifient. Cela garantit que la couleur de mise en surbrillance du focus, l'épaisseur du trait, etc., ne changent pas lorsque l'utilisateur passe d'une vue à l'autre avec un focus personnalisé ; et une vue avec la mise en surbrillance par défaut. Le dernier élément est une ondulation utilisée pour le toucher. Les valeurs par défaut utilisées pour les ressources en gras s'affichent comme suit:
De plus, une mise en surbrillance personnalisée est appelée lorsque le bouton couleur d'arrière-plan pour attirer l'attention de l'utilisateur, comme dans l'exemple ci-dessous. Cela peut rendre mise en surbrillance difficile à voir. Dans ce cas, spécifiez une mise en surbrillance personnalisée à l'aide de couleurs secondaires:
- (Android 11 QPR3, Android 11 Car,
Android 12)
car_ui_rotary_focus_fill_secondary_color
car_ui_rotary_focus_stroke_secondary_color
- (Android 12)
car_ui_rotary_focus_pressed_fill_secondary_color
car_ui_rotary_focus_pressed_stroke_secondary_color
Exemple :
Concentré, pas appuyé | Concentré, pressé |
Défilement par dispositif rotatif
Si votre application utilise des RecyclerView
, vous DEVEZ utiliser
CarUiRecyclerView
à la place. Cela garantit que votre UI est cohérente avec
d'autres, car la personnalisation d'un OEM s'applique à tous les CarUiRecyclerView
.
Si tous les éléments de votre liste sont sélectionnables, vous n'avez rien d'autre à faire. La navigation par dispositif rotatif déplace le curseur entre les éléments de la liste et celle-ci défile pour que l'élément sélectionné soit visible.
(Android 11 QPR3, Android 11 Car,
Android 12)
S'il y a à la fois des éléments
sélectionnables et non sélectionnables
ou si tous les éléments ne sont pas sélectionnables, vous pouvez activer le défilement par dispositif rotatif,
l'utilisateur d'utiliser le contrôleur rotatif pour faire défiler progressivement la liste sans l'ignorer.
éléments non sélectionnables. Pour activer le défilement par dispositif rotatif, définissez app:rotaryScrollEnabled
à true
.
(Android 11 QPR3, Android 11 Car,
Android 12)
Vous pouvez activer le défilement rotatif
vue déroulante, y compris avCarUiRecyclerView
, avec
setRotaryScrollEnabled()
dans CarUiUtils
. Dans ce cas,
vous devez:
- Faites en sorte que la vue déroulante soit sélectionnable lorsqu'aucun de ses les vues descendantes sélectionnables sont visibles,
- Désactivez la mise en surbrillance par défaut du focus sur la vue déroulante en appelant
setDefaultFocusHighlightEnabled(false)
afin que la vue déroulante ne semble pas être sélectionné, - Assurez-vous que la vue déroulante est sélectionnée avant ses descendants en appelant
setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS)
- Écoutez les MotionEvents avec
SOURCE_ROTARY_ENCODER
et au choixAXIS_VSCROLL
ouAXIS_HSCROLL
pour indiquer la distance à faire défiler et (à travers le panneau).
Lorsque le défilement par dispositif rotatif est activé sur une CarUiRecyclerView
et que l'utilisateur effectue une rotation
à une zone où aucune vue sélectionnable n'est présente, la barre de défilement passe du gris au bleu, comme si
pour indiquer que la barre de défilement est active. Vous pouvez implémenter un effet similaire si vous le souhaitez.
Les MotionEvents sont identiques à ceux générés par une molette sur une souris, à l'exception de la source.
Mode de manipulation directe
Normalement, les encouragements et la rotation parcourent l'interface utilisateur, tandis que le bouton central prendre des mesures, même si ce n'est pas toujours le cas. Par exemple, si un utilisateur souhaite ajuster le le volume de l'alarme, il peut utiliser le contrôleur rotatif pour accéder au curseur de volume, appuyer sur le bouton central, faites pivoter la télécommande pour régler le volume de l'alarme, puis appuyez sur le bouton "Retour" pour revenir à la navigation. C'est ce que l'on appelle le mode de manipulation directe (DM). Dans ce le contrôleur rotatif permet d'interagir directement avec la vue au lieu de naviguer.
Vous disposez de deux méthodes pour implémenter la gestion des données. Si vous avez uniquement besoin de gérer la rotation et la vue que vous souhaitez
de manipulation répond à ACTION_SCROLL_FORWARD
et
ACTION_SCROLL_BACKWARD
AccessibilityEvent
s de manière appropriée, utilisez le
mécanisme simple. Sinon, utilisez le mécanisme avancé.
Le mécanisme simple est la seule option dans les fenêtres système ; les applications peuvent utiliser l'un ou l'autre de ces mécanismes.
Mécanisme simple
(Android 11 QPR3, Android 11 Car,
Android 12)
Votre application doit appeler
DirectManipulationHelper.setSupportsRotateDirectly(View view, boolean enable)
RotaryService
détecte quand l'utilisateur est en mode MP et passe en mode MP lorsqu'il
appuie sur le bouton central lorsqu'une vue est sélectionnée. En mode MP, les rotations
ACTION_SCROLL_FORWARD
ou ACTION_SCROLL_BACKWARD
, et quitte le mode MP
lorsque l'utilisateur appuie sur
le bouton Retour. Le mécanisme simple active ou désactive
la vue lorsque vous activez
ou quittez le mode MP.
Pour indiquer visuellement que l'utilisateur est en mode MP, faites en sorte que votre vue soit différente.
lorsque cette option est sélectionnée. Par exemple, modifiez l'arrière-plan lorsque
android:state_selected
est true
.
Mécanisme avancé
L'application détermine quand RotaryService
passe en mode MP ou le quitte. Pour une
expérience utilisateur, le fait d'appuyer sur le bouton central alors que la vue DM est activée doit passer en mode MP
et le bouton Retour doit quitter
le mode MP. Si vous n'utilisez pas le bouton central et/ou le rappel automatique,
il peut s'agir d'autres moyens
de quitter le mode MP. Pour les applications telles que Maps, un bouton représentant
Vous pouvez utiliser le MP pour passer en mode MP.
Pour prendre en charge le mode MP avancé, une vue:
- (Android 11 QPR3, Android 11 Car,
Android 12) DOIT écouter un
KEYCODE_DPAD_CENTER
pour passer en mode MP et écouter l'événementKEYCODE_BACK
pour quitter le mode MP, en appelantDirectManipulationHelper.enableDirectManipulationMode()
dans chaque cas. Pour écouter ces événements, effectuez l'une des opérations suivantes: <ph type="x-smartling-placeholder">- </ph>
- Enregistrez un
OnKeyListener
.
ou
- Étendez la vue, puis remplacez sa méthode
dispatchKeyEvent()
.
- Enregistrez un
- DEVRAIT écouter les événements de rappel automatique (
KEYCODE_DPAD_UP
,KEYCODE_DPAD_DOWN
,KEYCODE_DPAD_LEFT
ouKEYCODE_DPAD_RIGHT
) si la vue doit gérer les rappels automatiques. - DEVRAIT écouter
MotionEvent
et obtenir le nombre de rotations dansAXIS_SCROLL
si la vue souhaite gérer la rotation. Pour ce faire, vous disposez de différentes méthodes: <ph type="x-smartling-placeholder">- </ph>
- Enregistrez un
OnGenericMotionListener
. - Étendez la vue et ignorez sa méthode
dispatchTouchEvent()
.
- Enregistrez un
- Pour éviter d'être bloqué en mode DM, vous DEVEZ quitter le mode DM lorsque le fragment ou l'activité de la vue appartient n'est pas interactive.
- DEVRAIT fournir un indicateur visuel indiquant que la vue est en mode MP.
Vous trouverez ci-dessous un exemple d'une vue personnalisée qui utilise le mode MP pour effectuer un panoramique et un zoom sur une carte:
/** Whether this view is in DM mode. */ private boolean mInDirectManipulationMode;
/** Initializes the view. Called by the constructors. */ private void init() { setOnKeyListener((view, keyCode, keyEvent) -> { boolean isActionUp = keyEvent.getAction() == KeyEvent.ACTION_UP; switch (keyCode) { // Always consume KEYCODE_DPAD_CENTER and KEYCODE_BACK events. case KeyEvent.KEYCODE_DPAD_CENTER: if (!mInDirectManipulationMode && isActionUp) { mInDirectManipulationMode = true; DirectManipulationHelper.enableDirectManipulationMode(this, true); setSelected(true); // visually indicate DM mode } return true; case KeyEvent.KEYCODE_BACK: if (mInDirectManipulationMode && isActionUp) { mInDirectManipulationMode = false; DirectManipulationHelper.enableDirectManipulationMode(this, false); setSelected(false); } return true; // Consume controller nudge events only when in DM mode. // When in DM mode, nudges pan the map. case KeyEvent.KEYCODE_DPAD_UP: if (!mInDirectManipulationMode) return false; if (isActionUp) pan(0f, -10f); return true; case KeyEvent.KEYCODE_DPAD_DOWN: if (!mInDirectManipulationMode) return false; if (isActionUp) pan(0f, 10f); return true; case KeyEvent.KEYCODE_DPAD_LEFT: if (!mInDirectManipulationMode) return false; if (isActionUp) pan(-10f, 0f); return true; case KeyEvent.KEYCODE_DPAD_RIGHT: if (!mInDirectManipulationMode) return false; if (isActionUp) pan(10f, 0f); return true; // Don't consume other key events. default: return false; } });
// When in DM mode, rotation zooms the map. setOnGenericMotionListener(((view, motionEvent) -> { if (!mInDirectManipulationMode) return false; float scroll = motionEvent.getAxisValue(MotionEvent.AXIS_SCROLL); zoom(10 * scroll); return true; })); }
@Override public void onPause() { if (mInDirectManipulationMode) { // To ensure that the user doesn't get stuck in DM mode, disable DM mode // when the fragment is not interactive (e.g., a dialog shows up). mInDirectManipulationMode = false; DirectManipulationHelper.enableDirectManipulationMode(this, false); } super.onPause(); }
Vous trouverez d'autres exemples dans le
Projet RotaryPlayground
.
ActivityView
Lorsque vous utilisez une ActivityView:
ActivityView
ne doit pas être sélectionnable.- (Android 11 QPR3, Android 11 Car,
obsolète dans Android 11)
Le contenu deActivityView
DOIT contenir unFocusParkingView
en tant que première vue sélectionnable, et sonapp:shouldRestoreFocus
L'attribut DOIT êtrefalse
. - Le contenu de
ActivityView
ne doit pas comporterandroid:focusByDefault
vues.
Pour l'utilisateur, les ActivityViews ne devraient avoir aucun effet sur la navigation, à l'exception de cette sélection.
zones ne peuvent pas s'étendre sur des ActivityViews. En d'autres termes, vous ne pouvez pas avoir
un seul domaine d'action qui
comporte du contenu à l'intérieur et à l'extérieur d'un ActivityView
. Si vous n'ajoutez pas
des FocusAreas vers votre ActivityView
, la racine de la hiérarchie des vues dans le
ActivityView
est considéré comme une zone de mise au point implicite.
Boutons qui fonctionnent lorsqu'ils sont enfoncés
La plupart des boutons déclenchent des actions lorsque l'utilisateur clique dessus. Certains boutons fonctionnent quand ils sont enfoncés.
Par exemple, les boutons Avance rapide et Retour arrière fonctionnent généralement lorsqu'ils sont enfoncés. Pour que ces
boutons compatibles avec le dispositif rotatif, écouter KEYCODE_DPAD_CENTER
KeyEvents
comme suit:
mButton.setOnKeyListener((v, keyCode, event) -> { if (keyCode != KEYCODE_DPAD_CENTER) { return false; } if (event.getAction() == ACTION_DOWN) { mButton.setPressed(true); mHandler.post(mRunnable); } else { mButton.setPressed(false); mHandler.removeCallbacks(mRunnable); } return true; });
mRunnable
effectue une action (comme un retour arrière) et se programme
s'exécuter après un certain délai.
Mode Écran tactile
Les utilisateurs peuvent utiliser un contrôleur rotatif pour interagir avec l'unité principale d'une voiture de deux manières : soit à l'aide du contrôleur rotatif, soit en touchant l'écran. Lorsque vous utilisez le contrôleur rotatif, l'une des vues sélectionnables est mise en surbrillance. Lorsque l'utilisateur appuie sur l'écran, la mise en surbrillance n'est pas sélectionnée s'affiche. L'utilisateur peut passer d'un mode de saisie à l'autre à tout moment:
- Rotatif → toucher Lorsque l'utilisateur touche l'écran, la mise en surbrillance disparaît.
- Appuyez sur → dispositif rotatif. Lorsque l'utilisateur pousse l'utilisateur, le fait pivoter ou appuie sur le bouton central, le surligner du texte sélectionné.
Les boutons "Retour" et "Accueil" n'ont aucun effet sur le mode de saisie.
Des superpositions rotatives sur le concept actuel d'Android
mode tactile.
Vous pouvez utiliser
View.isInTouchMode()
pour déterminer le mode de saisie utilisé par l'utilisateur. Vous pouvez utiliser
OnTouchModeChangeListener
pour écouter les changements. Cela permet de personnaliser votre interface utilisateur pour l'état actuel
d'entrée utilisateur, évitez d'apporter des modifications majeures, car elles peuvent déconcentrer.
Dépannage
Dans une application conçue pour l'écran tactile, il est courant d'avoir des vues sélectionnables imbriquées.
Par exemple, il peut y avoir un FrameLayout
autour d'un ImageButton
,
qui sont toutes deux sélectionnables. Cela ne nuit pas au toucher, mais peut nuire
l'expérience utilisateur pour le contrôleur rotatif,
car l'utilisateur doit faire pivoter le contrôleur deux fois
la vue interactive suivante. Pour une expérience utilisateur de qualité, Google vous recommande d'effectuer l'une des opérations suivantes :
la vue extérieure ou la vue intérieure sélectionnable, mais pas les deux.
Si un bouton ou un commutateur perd sa focus lorsqu'on appuie sur le contrôleur rotatif, l'un des ces conditions peuvent s'appliquer:
- Le bouton ou l'interrupteur est désactivé (brièvement ou indéfiniment) en raison de la
d'un utilisateur. Dans les deux cas, il existe deux façons de résoudre ce problème:
<ph type="x-smartling-placeholder">
- </ph>
- Laissez l'état
android:enabled
défini surtrue
et utilisez une valeur personnalisée pour griser le bouton ou le commutateur, comme décrit dans État personnalisé. - Utiliser un conteneur pour entourer le bouton ou le commutateur et rendre le conteneur sélectionnable au lieu du bouton ou du commutateur. (L'écouteur de clics doit se trouver sur le conteneur.)
- Laissez l'état
- Le bouton ou l'interrupteur est en cours de remplacement. Par exemple, l'action
effectuée lorsque le bouton
est activé ou le bouton bascule peut déclencher l'actualisation des actions disponibles.
entraînant le remplacement des nouveaux boutons par de nouveaux boutons. Il existe deux façons de résoudre ce problème:
<ph type="x-smartling-placeholder">
- </ph>
- Au lieu de créer un bouton ou un commutateur, définissez l'icône et/ou le texte bouton ou commutateur existant.
- Comme indiqué ci-dessus, ajoutez un conteneur sélectionnable autour du bouton ou du commutateur.
RotaryPlayground
RotaryPlayground
est une application de référence pour le dispositif rotatif. Utilisez-le pour apprendre à intégrer
les fonctionnalités rotatives
dans vos applications. RotaryPlayground
est inclus dans les builds de l'émulateur et dans
pour les appareils exécutant Android Automotive OS (AAOS).
- Dépôt
RotaryPlayground
:packages/apps/Car/tests/RotaryPlayground/
- Versions: Android 11 QPR3, Android 11 Car, et Android 12
L'application RotaryPlayground
affiche les onglets suivants à gauche:
- Fiches. Testez la navigation dans les zones d'action, en ignorant les éléments non sélectionnables. et la saisie de texte.
- Manipulation directe : Tester les widgets compatibles avec les méthodes simples et avancées de manipulation directe. Cet onglet est destiné à la manipulation directe dans la fenêtre de l'application.
- Manipulation de l'interface utilisateur système. Tester les widgets compatibles avec la manipulation directe dans les fenêtres système où seul le mode de manipulation directe simple est pris en charge.
- Grille : Testez la navigation par dispositif rotatif en forme de Z avec défilement.
- Notification. Testez les rappels automatiques pour recevoir et sortir des notifications prioritaires.
- Faire défiler. Testez le défilement entre les éléments sélectionnables et non sélectionnables. contenus.
- WebView : Testez la navigation entre les liens dans un
WebView
. FocusArea
personnalisé. Testez la personnalisation deFocusArea
:- Enveloppez.
android:focusedByDefault
etapp:defaultFocus
.
- Cibles de rappel explicites.
- Décaler les raccourcis.
FocusArea
sans vue sélectionnable.