연습: Xamarin.iOS에서 터치를 사용 하 여Walkthrough: Using Touch in Xamarin.iOS

이 연습에서는 다른 종류의 터치 이벤트에 응답 하는 코드를 작성 하는 방법에 설명 합니다.This walkthrough demonstrates how to write code that responds to different kinds of touch events. 각 예제는 별도 화면에 포함 되어 있습니다.Each example is contained in a separate screen:

각 섹션에는 처음부터 코드를 작성 하는 지침이 포함 됩니다.Each section contains instructions to write the code from scratch. 합니다 샘플 코드를 시작 이미 완료 된 스토리 보드 및 메뉴 화면 포함 되어 있습니다.The starting sample code already includes a complete storyboard and menu screen:

아래에 있는 스토리 보드에 코드를 추가 하 고 다양 한 유형의 iOS에서 사용할 수 있는 터치 이벤트에 대 한 자세한 지침을 따릅니다.Follow the instructions below to add code to the storyboard, and learn about the different types of touch events available in iOS. 또는 열을 완성 된 샘플 모든 작업을 수행 하십시오.Alternatively, open the finished sample to see everything working.

터치 샘플Touch Samples

이 샘플에서는 시연 하겠습니다 터치 Api의 일부입니다.In this sample, we will demonstrate some of the touch APIs. 터치 이벤트를 구현 하는 데 필요한 코드를 추가 하려면 다음이 단계를 수행 합니다.Follow these steps to add the code required to implement touch events:

  1. 프로젝트를 엽니다 Touch_Start합니다.Open the project Touch_Start. 첫 번째 프로젝트를 실행 해도, 모두 올바르게 되어 있는지 확인 하 고 터치 합니다 Touch 샘플 단추입니다.First run the project to make sure everything is okay, and touch the Touch Samples button. (사용할 수도 있지만 단추의 없음) 다음과 유사한 화면이 표시 됩니다.You should see a screen similar to the following (although none of the buttons will work):

  2. 파일을 편집 TouchViewController.cs 클래스에 다음 두 개의 인스턴스 변수를 추가 하 고 TouchViewController:Edit the file TouchViewController.cs and add the following two instance variables to the class TouchViewController:

    #region Private Variables
    private bool imageHighlighted = false;
    private bool touchStartedInside;
    #endregion
    
  3. 구현 된 TouchesBegan 메서드를 아래 코드에 표시 된 대로:Implement the TouchesBegan method, as shown in the code below:

    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;
            }
        }
    }
    

    이 메서드를 확인 하 여 작동는 UITouch 개체 및 존재 하는 경우 터치 발생 한 위치에 따라 일부 작업 수행:This method works by checking for a UITouch object, and if it exists perform some action based on where the touch occurred:

    • TouchImage 내 – 텍스트 표시 Touches Began 레이블 및 이미지를 변경 합니다.Inside TouchImage – display the text Touches Began in a label and change the image.
    • DoubleTouchImage 내 – 제스처를 두 번 눌러서 경우 표시 되는 이미지를 변경 합니다.Inside DoubleTouchImage – change the image displayed if the gesture was a double-tap.
    • DragImage 내 – 터치가 시작 했음을 나타내는 플래그를 설정 합니다.Inside DragImage – set a flag indicating that the touch has started. 메서드 TouchesMoved 여부를 확인 하려면이 플래그를 사용 하는 DragImage , 화면에서 이리저리 이동 해야 다음 단계에서 보게 될 것으로 합니다.The method TouchesMoved will use this flag to determine if DragImage should be moved around the screen or not, as we shall see in the next step.

    위의 코드는 개별 터치만 다루기, 여전히 동작이 없는 경우 사용자가 화면에서 해당 손가락을 이동 합니다.The above code only deals with individual touches, there is still no behavior if the user is moving their finger on the screen. 이동에 응답 하려면 구현 TouchesMoved 아래 코드에 표시 된 대로:To respond to movement, implement TouchesMoved as shown in the code below:

    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);
            }
        }
    }
    

    이 메서드를 가져옵니다는 UITouch 개체 및 터치 발생 한 위치를 확인 합니다.This method gets a UITouch object, and then checks to see where the touch occurred. 터치에서 발생 한 경우 TouchImage, 다음 화면에 표시 됩니다 터치 이동 텍스트입니다.If the touch occurred in TouchImage, then the text Touches Moved is displayed on the screen.

    하는 경우 touchStartedInside 가 true 이면 사용자에 게에 해당 손가락을 알게 DragImage 은 이동 하 고 있습니다.If touchStartedInside is true, then we know that the user has their finger on DragImage and is moving it around. 코드 이동 DragImage 사용자가 손가락을 화면에서 이리저리 이동 합니다.The code will move DragImage as the user moves their finger around the screen.

  4. 사용자가 자신의 화면에서 손가락을 뗄 때나 iOS에서 터치 이벤트를 취소 한 경우를 처리 해야 합니다.We need to handle the case when the user lifts his or her finger off the screen, or iOS cancels the touch event. 이 위해 구현 TouchesEndedTouchesCancelled 아래와 같이:For this, we will implement TouchesEnded and TouchesCancelled as shown below:

    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;
    }
    

    두이 방법 모두 다시 설정 됩니다는 touchStartedInside 플래그를 false로 합니다.Both of these methods will reset the touchStartedInside flag to false. TouchesEnded 표시도 TouchesEnded 화면의 합니다.TouchesEnded will also display TouchesEnded on the screen.

  5. 이 시점에서 터치 샘플 화면 완료 되었습니다.At this point the Touch Samples screen is finished. 어떻게 변경 되는지 확인 화면 이미지의 상호 작용 하는 대로 다음 스크린샷에 표시 된 대로:Notice how the screen changes as you interact with each of the images, as shown in the following screenshot:

제스처 인식기 샘플Gesture Recognizer Samples

합니다 이전 섹션 터치 이벤트를 사용 하 여 화면에서 이리저리 개체를 끌 하는 방법을 설명 합니다.The previous section demonstrated how to drag an object around the screen by using touch events. 이 섹션에서 터치 이벤트 제거 됩니다 하 고 다음 제스처 인식기를 사용 하는 방법을 보여 줍니다.In this section we will get rid of the touch events and show how to use the following gesture recognizers:

  • UIPanGestureRecognizer 끌어 화면에서 이리저리 이미지에 대 한 합니다.The UIPanGestureRecognizer for dragging an image around the screen.
  • UITapGestureRecognizer 화면에 두 번 탭 응답할 수 있습니다.The UITapGestureRecognizer to respond to double taps on the screen.

실행 하는 경우는 샘플 코드를 시작 를 클릭 합니다 제스처 인식기 샘플 단추를 다음 화면이 표시 됩니다:If you run the starting sample code and click on the Gesture Recognizer Samples button, you should see the following screen:

제스처 인식기를 구현 하려면 다음이 단계를 수행 합니다.Follow these steps to implement gesture recognizers:

  1. 파일을 편집 GestureViewController.cs 다음 인스턴스 변수를 추가 합니다.Edit the file GestureViewController.cs and add the following instance variable:

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

    이 인스턴스 변수 이미지의 이전 위치를 추적 하기 위해 필요 합니다.We need this instance variable to keep track of the previous location of the image. 팬 제스처 인식기를 사용할지를 originalImageFrame 를 화면에 이미지를 그리는 데 필요한 오프셋을 계산 하는 값입니다.The pan gesture recognizer will use the originalImageFrame value to calculate the offset required to redraw the image on the screen.

  2. 컨트롤러에 다음 메서드를 추가 합니다.Add the following method to the controller:

    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);
    }
    

    이 코드를 인스턴스화하는 UIPanGestureRecognizer 인스턴스 보기에 추가 합니다.This code instantiates a UIPanGestureRecognizer instance, and adds it to a view. 대상 메서드의 형태로 제스처를 할당 하 확인 HandleDrag –이 메서드는 다음 단계에서 제공 됩니다.Notice that we assign a target to the gesture in the form of the method HandleDrag – this method is provided in the next step.

  3. HandleDrag를 구현 하려면 컨트롤러에 다음 코드를 추가 합니다.To implement HandleDrag, add the following code to the controller:

    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;
        }
    }
    

    위의 코드는 먼저 제스처 인식기의 상태를 확인 하 고 화면 이미지를 이동 합니다.The code above will first check the state of the gesture recognizer and then move the image around the screen. 이 코드를 사용 하 여 컨트롤러를 지원할 수 있습니다 이제 화면에서 이리저리 하나의 이미지를 끌기.With this code in place, the controller can now support dragging the one image around the screen.

  4. 추가 된 UITapGestureRecognizer DoubleTouchImage에 표시 되는 이미지 변경 됩니다.Add a UITapGestureRecognizer that will change the image being displayed in DoubleTouchImage. 다음 메서드를 추가 합니다 GestureViewController 컨트롤러:Add the following method to the GestureViewController controller:

    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);
    }
    

    이 코드는 코드와 매우 비슷합니다는 UIPanGestureRecognizer 사용 하 여 대상에 대 한 대리자를 사용 하는 대신는 Action합니다.This code is very similar to the code for the UIPanGestureRecognizer but instead of using a delegate for a target we are using an Action.

  5. 우리가 해야 할 마지막으로 수정 ViewDidLoad 방금 추가한 메서드를 호출 합니다.The final thing we need to do is modify ViewDidLoad so that it calls the methods we just added. 다음 코드는 유사 하므로 ViewDidLoad를 변경 합니다.Change ViewDidLoad so it resembles the following code:

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

    값을 초기화 하는 것도 확인 originalImageFrame합니다.Notice as well that we initialize the value of originalImageFrame.

  6. 응용 프로그램을 실행 하 고 두 개의 이미지와 상호 작용 합니다.Run the application, and interact with the two images. 다음 스크린샷은 다음과 같습니다. 이러한 상호 작용의 예로The following screenshot is one example of these interactions:

사용자 지정 제스처 인식기Custom Gesture Recognizer

이 섹션에서 사용자 지정 제스처 인식기를 이전 섹션에서 개념 적용 합니다.In this section we will apply the concepts from previous sections to build a custom gesture recognizer. 사용자 지정 제스처 인식기는 서브 클래스 UIGestureRecognizer는 사용자에 "V"를 그릴 때 화면에서 인식 하 고 비트맵을 설정/해제 합니다.The custom gesture recognizer will subclasses UIGestureRecognizer, and will recognize when the user draws a “V” on the screen then toggle a bitmap. 다음 스크린샷은 다음과 같습니다.이 화면의 예The following screenshot is an example of this screen:

사용자 지정 제스처 인식기를 만들려면 다음이 단계를 수행 합니다.Follow these steps to create a custom gesture recognizer:

  1. 프로젝트에 새 클래스를 추가 CheckmarkGestureRecognizer, 고 다음 코드와 같습니다.Add a new class to the project named CheckmarkGestureRecognizer, and make it look like the following code:

    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
        }
    }
    

    Reset 메서드를 호출한 경우 합니다 State 속성을 변경 Recognized 또는 Ended합니다.The Reset method is called when the State property changes to either Recognized or Ended. 사용자 지정 제스처 인식기에서 설정 된 모든 내부 상태를 다시 설정 하는 시간입니다.This is the time to reset any internal state set in the custom gesture recognizer. 이제 클래스는 사용자 응용 프로그램과 상호 작용 하는 다음 번 새로 시작 하 고 제스처 인식을 다시 시도 수 수 있습니다.Now the class can start fresh next time the user interacts with the application, and be ready to re-attempt recognizing the gesture.

  2. 이제는 사용자 지정 제스처 인식기를 정의 했습니다 (CheckmarkGestureRecognizer) 편집 합니다 CustomGestureViewController.cs 파일을 다음 두 개의 인스턴스 변수를 추가:Now that we’ve defined a custom gesture recognizer (CheckmarkGestureRecognizer) edit the CustomGestureViewController.cs file and add the following two instance variables:

    #region Private Variables
    private bool isChecked = false;
    private CheckmarkGestureRecognizer checkmarkGesture;
    #endregion
    
  3. 를 인스턴스화 및 우리의 제스처 인식기를 구성 하려면 컨트롤러에 다음 메서드를 추가 합니다.To instantiate and configure our gesture recognizer, add the following method to the controller:

    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. 편집할 ViewDidLoad 호출 WireUpCheckmarkGestureRecognizer다음 코드 조각에 나와 있는 것 처럼:Edit ViewDidLoad so that it calls WireUpCheckmarkGestureRecognizer, as shown in the following code snippet:

    public override void ViewDidLoad()
    {
        base.ViewDidLoad();
    
        // Wire up the gesture recognizer
        WireUpCheckmarkGestureRecognizer();
    }
    
  5. 응용 프로그램을 실행 하 고 화면에 "V"를 그려 키를 누릅니다.Run the application, and try drawing a “V” on the screen. 표시 되는 이미지가 변경, 다음 스크린샷과에서 같이:You should see the image being displayed change, as shown in the following screenshots:

위의 세 가지 섹션에서는 터치 iOS에서 이벤트에 응답할 다양 한 방법을 설명 했습니다: 터치 이벤트를 기본 제공 제스처 인식기를 사용 하 여 또는 사용자 지정 제스처 인식기를 사용 하 여 합니다.The above three sections demonstrated different ways to respond to touch events in iOS: using touch events, built-in gesture recognizers, or with a custom gesture recognizer.