Rendre une vue personnalisée interactive

Essayer Compose
Jetpack Compose est le kit d'outils d'interface utilisateur recommandé pour Android. Découvrez comment utiliser les mises en page dans Compose.
<ph type="x-smartling-placeholder"></ph> Gestes →

Dessiner une interface utilisateur n'est qu'une partie de la création d'une vue personnalisée. Vous devez également Faites en sorte que votre vue réponde aux entrées utilisateur d'une manière qui ressemble le plus action du monde réel que vous imitez.

Faites en sorte que les objets de votre application se comportent comme des objets réels. Par exemple, ne laissez pas images de votre application sortent de l'existence et réapparaissent ailleurs, car les objets dans le monde réel ne le faites pas. Déplacez plutôt vos images d'un endroit une autre.

Les utilisateurs ressentent même un comportement ou des sentiments subtils dans une interface et réagissent mieux aux subtiles qui imitent le monde réel. Par exemple, lorsque les utilisateurs poussent un objet UI, leur donner un sentiment d'inertie au début qui retarde le mouvement. À la fin du mouvement, donnez-leur un sentiment de mouvement qui transporte l'objet au-delà faire glisser d'un geste vif.

Cette page explique comment utiliser les fonctionnalités du framework Android pour ajouter ces comportements réels à votre vue personnalisée.

Vous trouverez d'autres informations associées dans Présentation des événements d'entrée Animation des propriétés présentation.

Gérer les gestes de saisie

Comme de nombreux autres frameworks d'UI, Android est compatible avec un modèle d'événement d'entrée. Utilisateur se transforment en événements qui déclenchent des rappels, et vous pouvez ignorer pour personnaliser la manière dont votre application répond à l'utilisateur. L'entrée la plus courante dans le système Android est touch, qui déclenche onTouchEvent(android.view.MotionEvent) Ignorez cette méthode pour gérer l'événement comme suit:

Kotlin

override fun onTouchEvent(event: MotionEvent): Boolean {
    return super.onTouchEvent(event)
}

Java

@Override
   public boolean onTouchEvent(MotionEvent event) {
    return super.onTouchEvent(event);
   }

Les événements tactiles en eux-mêmes ne sont pas particulièrement utiles. Interfaces tactiles modernes définissent les interactions en termes de gestes : tapoter, tirer, pousser, effleurer d'un geste vif et zoomer. Pour convertir des événements tactiles bruts en gestes, Android fournit GestureDetector

Construire un GestureDetector en transmettant une instance d'une classe qui met en œuvre GestureDetector.OnGestureListener Si vous ne voulez traiter que quelques gestes, vous pouvez étendre GestureDetector.SimpleOnGestureListener au lieu d'implémenter GestureDetector.OnGestureListener de commande. Par exemple, ce code crée une classe qui étend GestureDetector.SimpleOnGestureListener et forçages onDown(MotionEvent)

Kotlin

private val myListener =  object : GestureDetector.SimpleOnGestureListener() {
    override fun onDown(e: MotionEvent): Boolean {
        return true
    }
}

private val detector: GestureDetector = GestureDetector(context, myListener)

Java

class MyListener extends GestureDetector.SimpleOnGestureListener {
   @Override
   public boolean onDown(MotionEvent e) {
       return true;
   }
}
detector = new GestureDetector(getContext(), new MyListener());

Que vous utilisiez ou non GestureDetector.SimpleOnGestureListener, toujours mettre en œuvre onDown() qui renvoie true. Cela est nécessaire car tous les gestes commencer par un message onDown(). Si vous renvoyez false de onDown(), en tant que GestureDetector.SimpleOnGestureListener, le système suppose ignorer le reste du geste, et les autres méthodes GestureDetector.OnGestureListener ne sont pas appelés. Retour uniquement false de onDown() si vous souhaitez ignorer un entier geste.

Après avoir implémenté GestureDetector.OnGestureListener et créé une instance de GestureDetector, vous pouvez utiliser GestureDetector pour interpréter les événements tactiles reçus dans onTouchEvent()

Kotlin

override fun onTouchEvent(event: MotionEvent): Boolean {
    return detector.onTouchEvent(event).let { result ->
        if (!result) {
            if (event.action == MotionEvent.ACTION_UP) {
                stopScrolling()
                true
            } else false
        } else true
    }
}

Java

@Override
public boolean onTouchEvent(MotionEvent event) {
   boolean result = detector.onTouchEvent(event);
   if (!result) {
       if (event.getAction() == MotionEvent.ACTION_UP) {
           stopScrolling();
           result = true;
       }
   }
   return result;
}

Lorsque vous transmettez à onTouchEvent() un événement tactile qui n'est pas à reconnaître dans le cadre d'un geste, il renvoie false. Vous pouvez ensuite exécuter votre propre code de détection de gestes personnalisé.

Créer un mouvement physiquement plausible

Les gestes sont un moyen efficace de contrôler les appareils à écran tactile, mais ils peuvent être contre-intuitifs et difficiles à mémoriser à moins qu'ils ne produisent physiquement des résultats plausibles.

Par exemple, supposons que vous souhaitiez implémenter un geste de balayage horizontal définit l'élément dessiné dans la vue pivotant autour de son axe vertical. Ce geste est logique si l'UI répond en se déplaçant rapidement dans la direction du glissement d'un geste vif, puis ralentit, comme si l'utilisateur appuie sur un volant et le fait tourner.

La documentation expliquant comment animer un défilement Geste pour expliquer en détail comment implémenter votre propre scoll comportemental. Mais simuler la sensation d'un volant n'est pas chose aisée. Beaucoup de physique et mathématiques sont nécessaires pour faire fonctionner un modèle de volant correctement. Heureusement, Android fournit des classes d'assistance pour simuler ce comportement et d'autres. La Scroller est la base de la gestion des gestes de glissement d'un volant.

Pour lancer un geste vif, appelez fling() avec la vitesse de départ et les valeurs minimale et maximale x et y de glissement d'un geste vif. Pour la valeur de vitesse, vous pouvez utiliser la valeur calculée par GestureDetector

Kotlin

fun onFling(e1: MotionEvent, e2: MotionEvent, velocityX: Float, velocityY: Float): Boolean {
    scroller.fling(
            currentX,
            currentY,
            (velocityX / SCALE).toInt(),
            (velocityY / SCALE).toInt(),
            minX,
            minY,
            maxX,
            maxY
    )
    postInvalidate()
    return true
}

Java

@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
   scroller.fling(currentX, currentY, velocityX / SCALE, velocityY / SCALE, minX, minY, maxX, maxY);
   postInvalidate();
    return true;
}
<ph type="x-smartling-placeholder">

L'appel à fling() configure le modèle physique pour le déplacement geste. Ensuite, mettez à jour Scroller en appelant Scroller.computeScrollOffset() à intervalles réguliers. computeScrollOffset() met à jour le l'état interne de l'objet Scroller en lisant l'heure actuelle et à l'aide du modèle physique pour calculer les positions x et y à cet en temps réel. Appeler getCurrX() et getCurrY() pour récupérer ces valeurs.

La plupart des vues transmettent les valeurs x et y de l'objet Scroller. directement aux scrollTo() Cet exemple est légèrement différent: il utilise la position de défilement actuelle X. pour définir l'angle de rotation de la vue.

Kotlin

scroller.apply {
    if (!isFinished) {
        computeScrollOffset()
        setItemRotation(currX)
    }
}

Java

if (!scroller.isFinished()) {
    scroller.computeScrollOffset();
    setItemRotation(scroller.getCurrX());
}

La classe Scroller calcule les positions de défilement pour vous, mais elle n'applique pas automatiquement ces positions à votre vue. Appliquer les nouvelles coordonnées pour que l'animation défilante soit fluide. Il existe deux façons procédez comme suit:

  • Forcer un redessin en appelant postInvalidate() après avoir appelé fling(). Cette technique nécessite que vous calculer les décalages de défilement onDraw() et appeler postInvalidate() à chaque décalage de défilement des modifications.
  • Configurez un ValueAnimator pour l'animer pendant le glissement d'un geste vif et ajouter un écouteur pour traiter les mises à jour de l'animation addUpdateListener() Cette technique vous permet d'animer les propriétés View

Facilitez la transition

Les utilisateurs s'attendent à ce qu'une interface utilisateur moderne passe facilement d'un état à un autre: éléments de l'interface utilisateur qui apparaissent et disparaissent en fondu et que des mouvements commencent et une fin en douceur au lieu de démarrer et de s'arrêter brusquement. Android animation de la propriété facilite les transitions.

Pour utiliser le système d'animation, chaque fois qu'une propriété modifie ce qui affecte votre ne modifiez pas directement la propriété. Utilisez plutôt ValueAnimator pour effectuer la modification. Dans l'exemple suivant, la modification du composant enfant sélectionné dans la vue rend l'intégralité de l'élément faire pivoter la vue de sorte que le pointeur de sélection soit centré. ValueAnimator modifie la rotation sur une période de plusieurs centaines millisecondes, au lieu de définir immédiatement la nouvelle valeur de rotation.

Kotlin

autoCenterAnimator = ObjectAnimator.ofInt(this, "Rotation", 0).apply {
    setIntValues(targetAngle)
    duration = AUTOCENTER_ANIM_DURATION
    start()
}

Java

autoCenterAnimator = ObjectAnimator.ofInt(this, "Rotation", 0);
autoCenterAnimator.setIntValues(targetAngle);
autoCenterAnimator.setDuration(AUTOCENTER_ANIM_DURATION);
autoCenterAnimator.start();

Si la valeur que vous souhaitez modifier est l'une des valeurs View de base l'animation est encore plus facile, car les vues intègrent ViewPropertyAnimator optimisé pour l'animation simultanée de plusieurs propriétés, comme dans l'exemple suivant:

Kotlin

animate()
    .rotation(targetAngle)
    .duration = ANIM_DURATION
    .start()

Java

animate().rotation(targetAngle).setDuration(ANIM_DURATION).start();