Partager via


Procédure pas à pas - Utilisation de Touch dans Android

Voyons comment utiliser les concepts de la section précédente dans une application de travail. Nous allons créer une application avec quatre activités. La première activité sera un menu ou un commutateur qui lancera les autres activités pour illustrer les différentes API. La capture d’écran suivante montre l’activité principale :

Exemple de capture d’écran avec le bouton Me tactile

La première activité, l’exemple tactile, montre comment utiliser des gestionnaires d’événements pour toucher les vues. L’activité Gesture Recognizer montre comment sous-classer Android.View.Views et gérer les événements, ainsi que comment gérer les mouvements de pincement. La troisième et dernière activité, Custom Gesture, montre comment utiliser des mouvements personnalisés. Pour faciliter le suivi et l’absorption, nous allons interrompre cette procédure pas à pas dans les sections, chaque section se concentrant sur l’une des activités.

Activité d’exemple tactile

  • Ouvrez le projet TouchWalkthrough_Start. MainActivity est tout à fait prêt à aller : c’est à nous d’implémenter le comportement tactile dans l’activité. Si vous exécutez l’application et cliquez sur Touch Sample, l’activité suivante doit démarrer :

    Capture d’écran de l’activité avec Les débuts tactiles affichés

  • Maintenant que nous avons confirmé que l’activité démarre, ouvrez le fichier TouchActivity.cs et ajoutez un gestionnaire pour l’événement Touch du ImageView:

    _touchMeImageView.Touch += TouchMeImageViewOnTouch;
    
  • Ensuite, ajoutez la méthode suivante à TouchActivity.cs :

    private void TouchMeImageViewOnTouch(object sender, View.TouchEventArgs touchEventArgs)
    {
        string message;
        switch (touchEventArgs.Event.Action & MotionEventActions.Mask)
        {
            case MotionEventActions.Down:
            case MotionEventActions.Move:
            message = "Touch Begins";
            break;
    
            case MotionEventActions.Up:
            message = "Touch Ends";
            break;
    
            default:
            message = string.Empty;
            break;
        }
    
        _touchInfoTextView.Text = message;
    }
    

Notez dans le code ci-dessus que nous traitons les actions et Down les Move mêmes. Cela est dû au fait que même si l’utilisateur peut ne pas lever son doigt, ImageViewil peut se déplacer ou la pression exercée par l’utilisateur peut changer. Ces types de modifications génèrent une Move action.

Chaque fois que l’utilisateur touche, ImageViewl’événement Touch est déclenché et notre gestionnaire affiche le message Touch Begins à l’écran, comme illustré dans la capture d’écran suivante :

Capture d’écran de l’activité avec Les débuts tactiles

Tant que l’utilisateur touche la ImageViewtouche, Touch Begins s’affiche dans le TextView. Lorsque l’utilisateur ne touche ImageViewplus, le message touch ends s’affiche dans la TextViewcapture d’écran suivante :

Capture d’écran de l’activité avec touch ends

Activité de reconnaissance de mouvement

Implémente maintenant l’activité Gesture Recognizer. Cette activité montre comment faire glisser une vue autour de l’écran et illustrer une façon d’implémenter un pincement à zoom.

  • Ajoutez une nouvelle activité à l’application appelée GestureRecognizer. Modifiez le code de cette activité afin qu’il ressemble au code suivant :

    public class GestureRecognizerActivity : Activity
    {
        protected override void OnCreate(Bundle bundle)
        {
            base.OnCreate(bundle);
            View v = new GestureRecognizerView(this);
            SetContentView(v);
        }
    }
    
  • Ajoutez une nouvelle vue Android au projet et nommez-le GestureRecognizerView. Ajoutez les variables suivantes à cette classe :

    private static readonly int InvalidPointerId = -1;
    
    private readonly Drawable _icon;
    private readonly ScaleGestureDetector _scaleDetector;
    
    private int _activePointerId = InvalidPointerId;
    private float _lastTouchX;
    private float _lastTouchY;
    private float _posX;
    private float _posY;
    private float _scaleFactor = 1.0f;
    
  • Ajoutez le constructeur suivant à GestureRecognizerView. Ce constructeur ajoute une ImageView à notre activité. À ce stade, le code ne sera toujours pas compilé : nous devons créer la classe MyScaleListener qui vous aidera à redimensionner le ImageView moment où l’utilisateur le pince :

    public GestureRecognizerView(Context context): base(context, null, 0)
    {
        _icon = context.Resources.GetDrawable(Resource.Drawable.Icon);
        _icon.SetBounds(0, 0, _icon.IntrinsicWidth, _icon.IntrinsicHeight);
        _scaleDetector = new ScaleGestureDetector(context, new MyScaleListener(this));
    }
    
  • Pour dessiner l’image sur notre activité, nous devons remplacer la OnDraw méthode de la classe View, comme indiqué dans l’extrait de code suivant. Ce code déplace la ImageView position spécifiée _posX et _posY redimensionne l’image en fonction du facteur de mise à l’échelle :

    protected override void OnDraw(Canvas canvas)
    {
        base.OnDraw(canvas);
        canvas.Save();
        canvas.Translate(_posX, _posY);
        canvas.Scale(_scaleFactor, _scaleFactor);
        _icon.Draw(canvas);
        canvas.Restore();
    }
    
  • Ensuite, nous devons mettre à jour la variable _scaleFactor d’instance lorsque l’utilisateur pince le ImageView. Nous allons ajouter une classe appelée MyScaleListener. Cette classe écoute les événements de mise à l’échelle qui seront déclenchés par Android lorsque l’utilisateur pince le ImageView. Ajoutez la classe interne suivante à GestureRecognizerView. Cette classe est un ScaleGesture.SimpleOnScaleGestureListener. Cette classe est une classe pratique que les écouteurs peuvent sous-classe lorsque vous êtes intéressé par un sous-ensemble de mouvements :

    private class MyScaleListener : ScaleGestureDetector.SimpleOnScaleGestureListener
    {
        private readonly GestureRecognizerView _view;
    
        public MyScaleListener(GestureRecognizerView view)
        {
            _view = view;
        }
    
        public override bool OnScale(ScaleGestureDetector detector)
        {
            _view._scaleFactor *= detector.ScaleFactor;
    
            // put a limit on how small or big the image can get.
            if (_view._scaleFactor > 5.0f)
            {
                _view._scaleFactor = 5.0f;
            }
            if (_view._scaleFactor < 0.1f)
            {
                _view._scaleFactor = 0.1f;
            }
    
            _view.Invalidate();
            return true;
        }
    }
    
  • La méthode suivante dans laquelle nous devons remplacer GestureRecognizerView est OnTouchEvent. Le code suivant répertorie l’implémentation complète de cette méthode. Il y a beaucoup de code ici, donc nous allons prendre une minute et regarder ce qui se passe ici. La première chose que cette méthode effectue est de mettre à l’échelle l’icône si nécessaire : elle est gérée en appelant _scaleDetector.OnTouchEvent. Ensuite, nous essayons de déterminer l’action appelée cette méthode :

    • Si l’utilisateur a touché l’écran, nous enregistrons les positions X et Y et l’ID du premier pointeur qui touchait l’écran.

    • Si l’utilisateur a déplacé son contact sur l’écran, nous allons déterminer jusqu’à quel point l’utilisateur a déplacé le pointeur.

    • Si l’utilisateur a levé son doigt sur l’écran, nous arrêterons de suivre les mouvements.

    public override bool OnTouchEvent(MotionEvent ev)
    {
        _scaleDetector.OnTouchEvent(ev);
    
        MotionEventActions action = ev.Action & MotionEventActions.Mask;
        int pointerIndex;
    
        switch (action)
        {
            case MotionEventActions.Down:
            _lastTouchX = ev.GetX();
            _lastTouchY = ev.GetY();
            _activePointerId = ev.GetPointerId(0);
            break;
    
            case MotionEventActions.Move:
            pointerIndex = ev.FindPointerIndex(_activePointerId);
            float x = ev.GetX(pointerIndex);
            float y = ev.GetY(pointerIndex);
            if (!_scaleDetector.IsInProgress)
            {
                // Only move the ScaleGestureDetector isn't already processing a gesture.
                float deltaX = x - _lastTouchX;
                float deltaY = y - _lastTouchY;
                _posX += deltaX;
                _posY += deltaY;
                Invalidate();
            }
    
            _lastTouchX = x;
            _lastTouchY = y;
            break;
    
            case MotionEventActions.Up:
            case MotionEventActions.Cancel:
            // We no longer need to keep track of the active pointer.
            _activePointerId = InvalidPointerId;
            break;
    
            case MotionEventActions.PointerUp:
            // check to make sure that the pointer that went up is for the gesture we're tracking.
            pointerIndex = (int) (ev.Action & MotionEventActions.PointerIndexMask) >> (int) MotionEventActions.PointerIndexShift;
            int pointerId = ev.GetPointerId(pointerIndex);
            if (pointerId == _activePointerId)
            {
                // This was our active pointer going up. Choose a new
                // action pointer and adjust accordingly
                int newPointerIndex = pointerIndex == 0 ? 1 : 0;
                _lastTouchX = ev.GetX(newPointerIndex);
                _lastTouchY = ev.GetY(newPointerIndex);
                _activePointerId = ev.GetPointerId(newPointerIndex);
            }
            break;
    
        }
        return true;
    }
    
  • Exécutez maintenant l’application et démarrez l’activité Gesture Recognizer. Quand il démarre l’écran doit ressembler à la capture d’écran ci-dessous :

    Écran de démarrage de Gesture Recognizer avec l’icône Android

  • Appuyez maintenant sur l’icône et faites-la glisser autour de l’écran. Essayez le mouvement de pincement à zoom. À un moment donné, votre écran peut ressembler à la capture d’écran suivante :

    Icône de déplacement des mouvements autour de l’écran

À ce stade, vous devez vous donner une paton sur le dos : vous venez d’implémenter un pincement pour zoomer dans une application Android ! Prenez une pause rapide et passez à la troisième et dernière activité dans cette procédure pas à pas, à l’aide de mouvements personnalisés.

Activité de mouvement personnalisé

L’écran final de cette procédure pas à pas utilise des mouvements personnalisés.

Dans le cadre de cette procédure pas à pas, la bibliothèque de mouvements a déjà été créée à l’aide de l’outil Mouvement et ajoutée au projet dans les ressources de fichier /raw/gestures. Avec ce peu de ménage hors de la route, permet d’accéder à l’activité finale dans la procédure pas à pas.

  • Ajoutez un fichier de disposition nommé custom_gesture_layout.axml au projet avec le contenu suivant. Le projet comporte déjà toutes les images dans le dossier Ressources :

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1" />
        <ImageView
            android:src="@drawable/check_me"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="3"
            android:id="@+id/imageView1"
            android:layout_gravity="center_vertical" />
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1" />
    </LinearLayout>
    
  • Ajoutez ensuite une nouvelle activité au projet et nommez-la CustomGestureRecognizerActivity.cs. Ajoutez deux variables d’instance à la classe, comme indiqué dans les deux lignes de code suivantes :

    private GestureLibrary _gestureLibrary;
    private ImageView _imageView;
    
  • Modifiez la OnCreate méthode de cette activité afin qu’elle ressemble au code suivant. Prenons une minute pour expliquer ce qui se passe dans ce code. La première chose que nous faisons est d’instancier un GestureOverlayView et de définir cela comme vue racine de l’activité. Nous affectons également un gestionnaire d’événements à l’événement GesturePerformed de GestureOverlayView. Ensuite, nous gonflons le fichier de disposition créé précédemment et ajoutez-le en tant qu’affichage enfant de l’objet GestureOverlayView. La dernière étape consiste à initialiser la variable _gestureLibrary et à charger le fichier de mouvements à partir des ressources de l’application. Si le fichier de mouvements ne peut pas être chargé pour une raison quelconque, il n’y a pas grand chose que cette activité peut faire, de sorte qu’elle est arrêtée :

    protected override void OnCreate(Bundle bundle)
    {
        base.OnCreate(bundle);
    
        GestureOverlayView gestureOverlayView = new GestureOverlayView(this);
        SetContentView(gestureOverlayView);
        gestureOverlayView.GesturePerformed += GestureOverlayViewOnGesturePerformed;
    
        View view = LayoutInflater.Inflate(Resource.Layout.custom_gesture_layout, null);
        _imageView = view.FindViewById<ImageView>(Resource.Id.imageView1);
        gestureOverlayView.AddView(view);
    
        _gestureLibrary = GestureLibraries.FromRawResource(this, Resource.Raw.gestures);
        if (!_gestureLibrary.Load())
        {
            Log.Wtf(GetType().FullName, "There was a problem loading the gesture library.");
            Finish();
        }
    }
    
  • La dernière chose que nous devons effectuer pour implémenter la méthode GestureOverlayViewOnGesturePerformed , comme illustré dans l’extrait de code suivant. Lorsque le GestureOverlayView message détecte un mouvement, il revient à cette méthode. La première chose que nous essayons d’obtenir un IList<Prediction> objet qui correspond au mouvement en appelant _gestureLibrary.Recognize(). Nous utilisons un peu linQ pour obtenir le Prediction score le plus élevé pour le mouvement.

    S’il n’y a pas eu de mouvement correspondant avec un score suffisamment élevé, le gestionnaire d’événements quitte sans rien faire. Sinon, nous case activée le nom de la prédiction et modifier l’image affichée en fonction du nom du mouvement :

    private void GestureOverlayViewOnGesturePerformed(object sender, GestureOverlayView.GesturePerformedEventArgs gesturePerformedEventArgs)
    {
        IEnumerable<Prediction> predictions = from p in _gestureLibrary.Recognize(gesturePerformedEventArgs.Gesture)
        orderby p.Score descending
        where p.Score > 1.0
        select p;
        Prediction prediction = predictions.FirstOrDefault();
    
        if (prediction == null)
        {
            Log.Debug(GetType().FullName, "Nothing seemed to match the user's gesture, so don't do anything.");
            return;
        }
    
        Log.Debug(GetType().FullName, "Using the prediction named {0} with a score of {1}.", prediction.Name, prediction.Score);
    
        if (prediction.Name.StartsWith("checkmark"))
        {
            _imageView.SetImageResource(Resource.Drawable.checked_me);
        }
        else if (prediction.Name.StartsWith("erase", StringComparison.OrdinalIgnoreCase))
        {
            // Match one of our "erase" gestures
            _imageView.SetImageResource(Resource.Drawable.check_me);
        }
    }
    
  • Exécutez l’application et démarrez l’activité Custom Gesture Recognizer. Il doit ressembler à la capture d’écran suivante :

    Capture d’écran avec l’image Vérifier moi

    Dessinez maintenant une case activée mark sur l’écran, et l’image bitmap affichée doit ressembler à celle affichée dans les captures d’écran suivantes :

    Dessin case activée mark, case activée mark est reconnu

    Enfin, dessinez un scribble sur l’écran. Le case activée box doit revenir à son image d’origine, comme illustré dans ces captures d’écran :

    Scribble sur l’écran, l’image d’origine s’affiche

Vous avez maintenant une compréhension de l’intégration des interactions tactiles et des mouvements dans une application Android à l’aide de Xamarin.Android.