Freigeben über


Exemplarische Vorgehensweise: Verwenden von Touch in Xamarin.iOS

In dieser exemplarischen Vorgehensweise wird das Schreiben von Code veranschaulicht, der auf verschiedene Arten von Touchereignissen reagiert. Jedes Beispiel ist in einem separaten Bildschirm enthalten:

Jeder Abschnitt enthält Anweisungen zum Schreiben des Codes von Grund auf.

Folgen Sie den nachstehenden Anweisungen, um dem Storyboard Code hinzuzufügen, und erfahren Sie mehr über die verschiedenen Arten von Touchereignissen, die in iOS verfügbar sind.

Touchbeispiele

In diesem Beispiel veranschaulichen wir einige der Touch-APIs. Führen Sie die folgenden Schritte aus, um den code hinzuzufügen, der zum Implementieren von Touchereignissen erforderlich ist:

  1. Öffnen Sie das Projekt Touch_Start. Führen Sie zunächst das Projekt aus, um sicherzustellen, dass alles in Ordnung ist, und tippen Sie auf die Schaltfläche "Touchbeispiele ". Es sollte ein Bildschirm wie folgt angezeigt werden (obwohl keine der Schaltflächen funktioniert):

    Beispiel-App mit nicht funktionierenden Schaltflächen

  2. Bearbeiten Sie die Datei TouchViewController.cs , und fügen Sie der Klasse TouchViewControllerdie folgenden beiden Instanzvariablen hinzu:

    #region Private Variables
    private bool imageHighlighted = false;
    private bool touchStartedInside;
    #endregion
    
  3. Implementieren Sie die TouchesBegan Methode, wie im folgenden Code gezeigt:

    public override void TouchesBegan(NSSet touches, UIEvent evt)
    {
        base.TouchesBegan(touches, evt);
    
        // If Multitouch is enabled, report the number of fingers down
        TouchStatus.Text = string.Format ("Number of fingers {0}", touches.Count);
    
        // Get the current touch
        UITouch touch = touches.AnyObject as UITouch;
        if (touch != null)
        {
            // Check to see if any of the images have been touched
            if (TouchImage.Frame.Contains(touch.LocationInView(TouchView)))
            {
                // Fist image touched
                TouchImage.Image = UIImage.FromBundle("TouchMe_Touched.png");
                TouchStatus.Text = "Touches Began";
            } else if (touch.TapCount == 2 && DoubleTouchImage.Frame.Contains(touch.LocationInView(TouchView)))
            {
                // Second image double-tapped, toggle bitmap
                if (imageHighlighted)
                {
                    DoubleTouchImage.Image = UIImage.FromBundle("DoubleTapMe.png");
                    TouchStatus.Text = "Double-Tapped Off";
                }
                else
                {
                    DoubleTouchImage.Image = UIImage.FromBundle("DoubleTapMe_Highlighted.png");
                    TouchStatus.Text = "Double-Tapped On";
                }
                imageHighlighted = !imageHighlighted;
            } else if (DragImage.Frame.Contains(touch.LocationInView(View)))
            {
                // Third image touched, prepare to drag
                touchStartedInside = true;
            }
        }
    }
    

    Diese Methode funktioniert, indem nach einem UITouch Objekt gesucht wird und ob es vorhanden ist, eine Aktion basierend auf dem Ort der Berührung ausführen:

    • Inside TouchImage – Zeigen Sie den Text Touches Began in einer Beschriftung an, und ändern Sie das Bild.
    • Innerhalb von DoubleTouchImage – Ändern Sie das angezeigte Bild, wenn die Geste doppeltippen wurde.
    • Legen Sie in DragImage eine Kennzeichnung fest, die angibt, dass die Toucheingabe gestartet wurde. Die Methode TouchesMoved wird diese Kennzeichnung verwenden, um zu bestimmen, ob DragImage der Bildschirm bewegt werden soll oder nicht, wie wir im nächsten Schritt sehen werden.

    Der obige Code behandelt nur einzelne Fingereingaben, es gibt immer noch kein Verhalten, wenn der Benutzer seinen Finger auf dem Bildschirm bewegt. Um auf Bewegung zu reagieren, implementieren Sie TouchesMoved dies wie im folgenden Code dargestellt:

    public override void TouchesMoved(NSSet touches, UIEvent evt)
    {
        base.TouchesMoved(touches, evt);
        // get the touch
        UITouch touch = touches.AnyObject as UITouch;
        if (touch != null)
        {
            //==== IMAGE TOUCH
            if (TouchImage.Frame.Contains(touch.LocationInView(TouchView)))
            {
                TouchStatus.Text = "Touches Moved";
            }
    
            //==== IMAGE DRAG
            // check to see if the touch started in the drag me image
            if (touchStartedInside)
            {
                // move the shape
                float offsetX = touch.PreviousLocationInView(View).X - touch.LocationInView(View).X;
                float offsetY = touch.PreviousLocationInView(View).Y - touch.LocationInView(View).Y;
                DragImage.Frame = new RectangleF(new PointF(DragImage.Frame.X - offsetX, DragImage.Frame.Y - offsetY), DragImage.Frame.Size);
            }
        }
    }
    

    Diese Methode ruft ein UITouch Objekt ab und überprüft dann, wo die Berührung aufgetreten ist. Wenn die Toucheingabe erfolgt TouchImageist, wird der Text "Verschoben" auf dem Bildschirm angezeigt.

    Wenn touchStartedInside dies der Fall ist, wissen wir, dass der Benutzer seinen Finger an den DragImage Finger hat und ihn bewegt. Der Code bewegt sich DragImage , wenn der Benutzer seinen Finger um den Bildschirm bewegt.

  4. Wir müssen den Fall behandeln, wenn der Benutzer seinen Finger vom Bildschirm hebt, oder iOS bricht das Touchereignis ab. Hierfür implementieren TouchesEnded wir und TouchesCancelled wie unten dargestellt:

    public override void TouchesCancelled(NSSet touches, UIEvent evt)
    {
        base.TouchesCancelled(touches, evt);
    
        // reset our tracking flags
        touchStartedInside = false;
        TouchImage.Image = UIImage.FromBundle("TouchMe.png");
        TouchStatus.Text = "";
    }
    
    public override void TouchesEnded(NSSet touches, UIEvent evt)
    {
        base.TouchesEnded(touches, evt);
        // get the touch
        UITouch touch = touches.AnyObject as UITouch;
        if (touch != null)
        {
            //==== IMAGE TOUCH
            if (TouchImage.Frame.Contains(touch.LocationInView(TouchView)))
            {
                TouchImage.Image = UIImage.FromBundle("TouchMe.png");
                TouchStatus.Text = "Touches Ended";
            }
        }
        // reset our tracking flags
        touchStartedInside = false;
    }
    

    Beide Methoden setzen die touchStartedInside Kennzeichnung auf "false" zurück. TouchesEnded wird auch auf dem Bildschirm angezeigt TouchesEnded .

  5. An diesem Punkt ist der Bildschirm "Touchbeispiele" fertig. Beachten Sie, wie sich der Bildschirm während der Interaktion mit den einzelnen Bildern ändert, wie im folgenden Screenshot gezeigt:

    Der Startbildschirm der App

    Der Bildschirm, nachdem der Benutzer eine Schaltfläche gezogen hat

Beispiele für die Gestikerkennung

Im vorherigen Abschnitt wurde gezeigt, wie Sie ein Objekt mithilfe von Touchereignissen um den Bildschirm ziehen. In diesem Abschnitt werden die Touchereignisse entfernt und gezeigt, wie sie die folgenden Gestenerkennungen verwenden:

  • Zum UIPanGestureRecognizer Ziehen eines Bilds um den Bildschirm.
  • Auf UITapGestureRecognizer dem Bildschirm doppeltippen Sie auf den Bildschirm.

Führen Sie die folgenden Schritte aus, um Gestenerkennungen zu implementieren:

  1. Bearbeiten Sie die Datei GestureViewController.cs , und fügen Sie die folgende Instanzvariable hinzu:

    #region Private Variables
    private bool imageHighlighted = false;
    private RectangleF originalImageFrame = RectangleF.Empty;
    #endregion
    

    Wir benötigen diese Instanzvariable, um den vorherigen Speicherort des Bilds nachzuverfolgen. Die Verschiebungsgestenerkennung verwendet den originalImageFrame Wert, um den Offset zu berechnen, der zum Neuzeichnen des Bilds auf dem Bildschirm erforderlich ist.

  2. Fügen Sie dem Controller die folgende Methode hinzu:

    private void WireUpDragGestureRecognizer()
    {
        // Create a new tap gesture
        UIPanGestureRecognizer gesture = new UIPanGestureRecognizer();
    
        // Wire up the event handler (have to use a selector)
        gesture.AddTarget(() => HandleDrag(gesture));  // to be defined
    
        // Add the gesture recognizer to the view
        DragImage.AddGestureRecognizer(gesture);
    }
    

    Dieser Code instanziiert eine UIPanGestureRecognizer Instanz und fügt sie einer Ansicht hinzu. Beachten Sie, dass wir der Geste in Form der Methode HandleDrag ein Ziel zuweisen – diese Methode wird im nächsten Schritt bereitgestellt.

  3. Um HandleDrag zu implementieren, fügen Sie dem Controller den folgenden Code hinzu:

    private void HandleDrag(UIPanGestureRecognizer recognizer)
    {
        // If it's just began, cache the location of the image
        if (recognizer.State == UIGestureRecognizerState.Began)
        {
            originalImageFrame = DragImage.Frame;
        }
    
        // Move the image if the gesture is valid
        if (recognizer.State != (UIGestureRecognizerState.Cancelled | UIGestureRecognizerState.Failed
            | UIGestureRecognizerState.Possible))
        {
            // Move the image by adding the offset to the object's frame
            PointF offset = recognizer.TranslationInView(DragImage);
            RectangleF newFrame = originalImageFrame;
            newFrame.Offset(offset.X, offset.Y);
            DragImage.Frame = newFrame;
        }
    }
    

    Der obige Code überprüft zuerst den Zustand der Gestikerkennung und bewegt dann das Bild um den Bildschirm. Mit diesem Code kann der Controller jetzt das Ziehen des bilds um den Bildschirm unterstützen.

  4. Fügen Sie ein UITapGestureRecognizer , das das Bild ändert, das in DoubleTouchImage angezeigt wird. Fügen Sie dem GestureViewController Controller die folgende Methode hinzu:

    private void WireUpTapGestureRecognizer()
    {
        // Create a new tap gesture
        UITapGestureRecognizer tapGesture = null;
    
        // Report touch
        Action action = () => {
            TouchStatus.Text = string.Format("Image touched at: {0}",tapGesture.LocationOfTouch(0, DoubleTouchImage));
    
            // Toggle the image
            if (imageHighlighted)
            {
                DoubleTouchImage.Image = UIImage.FromBundle("DoubleTapMe.png");
            }
            else
            {
                DoubleTouchImage.Image = UIImage.FromBundle("DoubleTapMe_Highlighted.png");
            }
            imageHighlighted = !imageHighlighted;
        };
    
        tapGesture = new UITapGestureRecognizer(action);
    
        // Configure it
        tapGesture.NumberOfTapsRequired = 2;
    
        // Add the gesture recognizer to the view
        DoubleTouchImage.AddGestureRecognizer(tapGesture);
    }
    

    Dieser Code ist dem Code für den UIPanGestureRecognizer Code sehr ähnlich, aber anstatt einen Delegat für ein Ziel zu verwenden, verwenden wir eine Action.

  5. Das Letzte, was wir tun müssen, ist die Änderung ViewDidLoad , damit sie die soeben hinzugefügten Methoden aufruft. Ändern Sie ViewDidLoad so, dass es dem folgenden Code ähnelt:

    public override void ViewDidLoad()
    {
        base.ViewDidLoad();
    
        Title = "Gesture Recognizers";
    
        // Save initial state
        originalImageFrame = DragImage.Frame;
    
        WireUpTapGestureRecognizer();
        WireUpDragGestureRecognizer();
    }
    

    Beachten Sie auch, dass wir den Wert von originalImageFrame.

  6. Führen Sie die Anwendung aus, und interagieren Sie mit den beiden Bildern. Der folgende Screenshot ist ein Beispiel für diese Interaktionen:

    Dieser Screenshot zeigt eine Ziehinteraktion.

Benutzerdefinierte Gestenerkennung

In diesem Abschnitt wenden wir die Konzepte aus vorherigen Abschnitten an, um eine benutzerdefinierte Gestenerkennung zu erstellen. Die benutzerdefinierte Gestenerkennung unterklassen UIGestureRecognizerund erkennt, wenn der Benutzer ein "V" auf dem Bildschirm zeichnet und dann eine Bitmap ein-/ausschalten kann. Der folgende Screenshot ist ein Beispiel für diesen Bildschirm:

Die App erkennt, wenn der Benutzer ein V auf dem Bildschirm zeichnet.

Führen Sie die folgenden Schritte aus, um eine benutzerdefinierte Gestenerkennung zu erstellen:

  1. Fügen Sie dem Projekt eine neue Klasse mit dem Namen CheckmarkGestureRecognizerhinzu, und stellen Sie sicher, dass sie wie der folgende Code aussieht:

    using System;
    using CoreGraphics;
    using Foundation;
    using UIKit;
    
    namespace Touch
    {
        public class CheckmarkGestureRecognizer : UIGestureRecognizer
        {
            #region Private Variables
            private CGPoint midpoint = CGPoint.Empty;
            private bool strokeUp = false;
            #endregion
    
            #region Override Methods
            /// <summary>
            ///   Called when the touches end or the recognizer state fails
            /// </summary>
            public override void Reset()
            {
                base.Reset();
    
                strokeUp = false;
                midpoint = CGPoint.Empty;
            }
    
            /// <summary>
            ///   Is called when the fingers touch the screen.
            /// </summary>
            public override void TouchesBegan(NSSet touches, UIEvent evt)
            {
                base.TouchesBegan(touches, evt);
    
                // we want one and only one finger
                if (touches.Count != 1)
                {
                    base.State = UIGestureRecognizerState.Failed;
                }
    
                Console.WriteLine(base.State.ToString());
            }
    
            /// <summary>
            ///   Called when the touches are cancelled due to a phone call, etc.
            /// </summary>
            public override void TouchesCancelled(NSSet touches, UIEvent evt)
            {
                base.TouchesCancelled(touches, evt);
                // we fail the recognizer so that there isn't unexpected behavior
                // if the application comes back into view
                base.State = UIGestureRecognizerState.Failed;
            }
    
            /// <summary>
            ///   Called when the fingers lift off the screen
            /// </summary>
            public override void TouchesEnded(NSSet touches, UIEvent evt)
            {
                base.TouchesEnded(touches, evt);
                //
                if (base.State == UIGestureRecognizerState.Possible && strokeUp)
                {
                    base.State = UIGestureRecognizerState.Recognized;
                }
    
                Console.WriteLine(base.State.ToString());
            }
    
            /// <summary>
            ///   Called when the fingers move
            /// </summary>
            public override void TouchesMoved(NSSet touches, UIEvent evt)
            {
                base.TouchesMoved(touches, evt);
    
                // if we haven't already failed
                if (base.State != UIGestureRecognizerState.Failed)
                {
                    // get the current and previous touch point
                    CGPoint newPoint = (touches.AnyObject as UITouch).LocationInView(View);
                    CGPoint previousPoint = (touches.AnyObject as UITouch).PreviousLocationInView(View);
    
                    // if we're not already on the upstroke
                    if (!strokeUp)
                    {
                        // if we're moving down, just continue to set the midpoint at
                        // whatever point we're at. when we start to stroke up, it'll stick
                        // as the last point before we upticked
                        if (newPoint.X >= previousPoint.X && newPoint.Y >= previousPoint.Y)
                        {
                            midpoint = newPoint;
                        }
                        // if we're stroking up (moving right x and up y [y axis is flipped])
                        else if (newPoint.X >= previousPoint.X && newPoint.Y <= previousPoint.Y)
                        {
                            strokeUp = true;
                        }
                        // otherwise, we fail the recognizer
                        else
                        {
                            base.State = UIGestureRecognizerState.Failed;
                        }
                    }
                }
    
                Console.WriteLine(base.State.ToString());
            }
            #endregion
        }
    }
    

    Die Reset-Methode wird aufgerufen, wenn die State Eigenschaft entweder Recognized oder Ended. Dies ist die Zeit, um jeden internen Zustand zurückzusetzen, der in der benutzerdefinierten Gestikerkennung festgelegt ist. Jetzt kann die Klasse neu gestartet werden, wenn der Benutzer das nächste Mal mit der Anwendung interagiert, und bereit sein, die Geste erneut zu erkennen.

  2. Nachdem wir nun eine benutzerdefinierte GestenerkennungCheckmarkGestureRecognizer () definiert haben, bearbeiten wir die CustomGestureViewController.cs Datei und fügen die folgenden beiden Instanzvariablen hinzu:

    #region Private Variables
    private bool isChecked = false;
    private CheckmarkGestureRecognizer checkmarkGesture;
    #endregion
    
  3. Um unsere Gestenerkennung zu instanziieren und zu konfigurieren, fügen Sie dem Controller die folgende Methode hinzu:

    private void WireUpCheckmarkGestureRecognizer()
    {
        // Create the recognizer
        checkmarkGesture = new CheckmarkGestureRecognizer();
    
        // Wire up the event handler
        checkmarkGesture.AddTarget(() => {
            if (checkmarkGesture.State == (UIGestureRecognizerState.Recognized | UIGestureRecognizerState.Ended))
            {
                if (isChecked)
                {
                    CheckboxImage.Image = UIImage.FromBundle("CheckBox_Unchecked.png");
                }
                else
                {
                    CheckboxImage.Image = UIImage.FromBundle("CheckBox_Checked.png");
                }
                isChecked = !isChecked;
            }
        });
    
        // Add the gesture recognizer to the view
        View.AddGestureRecognizer(checkmarkGesture);
    }
    
  4. Bearbeiten Sie ViewDidLoad , sodass sie aufgerufen wird WireUpCheckmarkGestureRecognizer, wie im folgenden Codeausschnitt gezeigt:

    public override void ViewDidLoad()
    {
        base.ViewDidLoad();
    
        // Wire up the gesture recognizer
        WireUpCheckmarkGestureRecognizer();
    }
    
  5. Führen Sie die Anwendung aus, und versuchen Sie, auf dem Bildschirm ein "V" zu zeichnen. Wie in den folgenden Screenshots gezeigt, sollte das Angezeigte Bild angezeigt werden:

    Die aktivierte Schaltfläche

    Die Schaltfläche wurde deaktiviert.

In den obigen drei Abschnitten wurden verschiedene Möglichkeiten zum Reagieren auf Touchereignisse in iOS veranschaulicht: Verwenden von Touchereignissen, integrierten Gestenerkennungen oder mit einer benutzerdefinierten Gestenerkennung.