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:
- Touchbeispiele – reagieren auf Touchereignisse.
- Beispiele für die Gestikerkennung – verwenden integrierte Gestenerkennungen.
- Beispiel für die benutzerdefinierte Gestenerkennung – Erstellen einer benutzerdefinierten Gestenerkennung.
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:
Ö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):
Bearbeiten Sie die Datei TouchViewController.cs , und fügen Sie der Klasse
TouchViewController
die folgenden beiden Instanzvariablen hinzu:#region Private Variables private bool imageHighlighted = false; private bool touchStartedInside; #endregion
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, obDragImage
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 erfolgtTouchImage
ist, wird der Text "Verschoben" auf dem Bildschirm angezeigt.Wenn
touchStartedInside
dies der Fall ist, wissen wir, dass der Benutzer seinen Finger an denDragImage
Finger hat und ihn bewegt. Der Code bewegt sichDragImage
, wenn der Benutzer seinen Finger um den Bildschirm bewegt.- Inside TouchImage – Zeigen Sie den Text
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 undTouchesCancelled
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 angezeigtTouchesEnded
.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:
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:
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.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 MethodeHandleDrag
ein Ziel zuweisen – diese Methode wird im nächsten Schritt bereitgestellt.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.
Fügen Sie ein
UITapGestureRecognizer
, das das Bild ändert, das in DoubleTouchImage angezeigt wird. Fügen Sie demGestureViewController
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 eineAction
.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
.Führen Sie die Anwendung aus, und interagieren Sie mit den beiden Bildern. Der folgende Screenshot ist ein Beispiel für diese Interaktionen:
Benutzerdefinierte Gestenerkennung
In diesem Abschnitt wenden wir die Konzepte aus vorherigen Abschnitten an, um eine benutzerdefinierte Gestenerkennung zu erstellen. Die benutzerdefinierte Gestenerkennung unterklassen UIGestureRecognizer
und 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:
Führen Sie die folgenden Schritte aus, um eine benutzerdefinierte Gestenerkennung zu erstellen:
Fügen Sie dem Projekt eine neue Klasse mit dem Namen
CheckmarkGestureRecognizer
hinzu, 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 entwederRecognized
oderEnded
. 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.Nachdem wir nun eine benutzerdefinierte Gestenerkennung
CheckmarkGestureRecognizer
() 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
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); }
Bearbeiten Sie
ViewDidLoad
, sodass sie aufgerufen wirdWireUpCheckmarkGestureRecognizer
, wie im folgenden Codeausschnitt gezeigt:public override void ViewDidLoad() { base.ViewDidLoad(); // Wire up the gesture recognizer WireUpCheckmarkGestureRecognizer(); }
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:
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.