Xamarin.iOS에서 추적 하는 멀티 터치 손가락Multi-Touch Finger Tracking in Xamarin.iOS

이 문서에서는 여러 손가락에서 터치 이벤트를 추적 하는 방법을 보여 줍니다.This document demonstrates how to track touch events from multiple fingers

멀티 터치 응용 프로그램 화면에서 동시에 이동 하는 대로 각 손가락을 추적 해야 할 경우 경우가 있습니다.There are times when a multi-touch application needs to track individual fingers as they move simultaneously on the screen. 일반적인 응용 프로그램을 하나의 finger-paint 프로그램입니다.One typical application is a finger-paint program. 사용자를 한 손가락으로 그릴 수 있지만 한 번에 여러 손가락으로 그릴 수 있게 되기를 원하는 합니다.You want the user to be able to draw with a single finger, but also to draw with multiple fingers at once. 프로그램이 여러 터치 이벤트를 처리할 때 이러한 두 손가락 사이의 구분 해야 합니다.As your program processes multiple touch events, it needs to distinguish between these fingers.

손가락 먼저 화면을 터치, iOS 만듭니다는 UITouch 해당 지문에 대 한 개체입니다.When a finger first touches the screen, iOS creates a UITouch object for that finger. 이 개체 손가락 화면에서 이동 하 고이 시점에서 개체가 삭제 되는 화면에서 다음가 뗄 동일 합니다.This object remains the same as the finger moves on the screen and then lifts from the screen, at which point the object is disposed. 추적 하기 위해 손가락을 프로그램이이 저장 하지 않아야 UITouch 직접 개체입니다.To keep track of fingers, a program should avoid storing this UITouch object directly. 대신 사용할 수는 Handle 형식의 속성 IntPtr 고유 하 게 식별 이러한 UITouch 개체입니다.Instead, it can use the Handle property of type IntPtr to uniquely identify these UITouch objects.

거의 항상 각 손가락을 추적 하는 프로그램에는 터치 추적에 대 한 사전 유지 관리 합니다.Almost always, a program that tracks individual fingers maintains a dictionary for touch tracking. IOS 프로그램에 대 한 사전 키는 Handle 특정 손가락을 식별 하는 값입니다.For an iOS program, the dictionary key is the Handle value that identifies a particular finger. 사전 값은 응용 프로그램에 따라 달라 집니다.The dictionary value depends on the application. 핑거 페인트 (릴리스 touch)에서 각 손가락 스트로크는 손가락을 사용 하 여 그리는 선을 렌더링 하는 데 필요한 모든 정보를 포함 하는 개체와 연결 된 프로그램입니다.In the FingerPaint program, each finger stroke (from touch to release) is associated with an object that contains all the information necessary to render the line drawn with that finger. 프로그램은 정의 하는 작은 FingerPaintPolyline 이 목적을 위해 클래스:The program defines a small FingerPaintPolyline class for this purpose:

class FingerPaintPolyline
{
    public FingerPaintPolyline()
    {
        Path = new CGPath();
    }

    public CGColor Color { set; get; }

    public float StrokeWidth { set; get; }

    public CGPath Path { private set; get; }
}

각 폴리라인에 있고 색, 스트로크 너비는 iOS 그래픽 CGPath 누적를 그릴 때 줄의 여러 요소를 렌더링 하는 개체입니다.Each polyline has a color, a stroke width, and an iOS graphics CGPath object to accumulate and render multiple points of the line as it's being drawn.

나머지 모든 아래에 표시 된 코드에 포함 되어는 UIView 라는 파생 FingerPaintCanvasView합니다.All the rest of the code shown below is contained in a UIView derivative named FingerPaintCanvasView. 클래스 형식의 개체를 사전 유지 관리는 FingerPaintPolyline 적극적으로 하나 이상의 손가락으로 그릴 되는 동안:That class maintains a dictionary of objects of type FingerPaintPolyline during the time that they are actively being drawn by one or more fingers:

Dictionary<IntPtr, FingerPaintPolyline> inProgressPolylines = new Dictionary<IntPtr, FingerPaintPolyline>();

이 사전에 뷰를 빠르게 가져올 수 있습니다는 FingerPaintPolyline 각 손가락 연관 된 정보에 따라는 Handle 의 속성을 UITouch 개체입니다.This dictionary allows the view to quickly obtain the FingerPaintPolyline information associated with each finger based on the Handle property of the UITouch object.

합니다 FingerPaintCanvasView 클래스도 유지 관리는 List 완료 된 폴리라인에 개체:The FingerPaintCanvasView class also maintains a List object for the polylines that have been completed:

List<FingerPaintPolyline> completedPolylines = new List<FingerPaintPolyline>();

이 개체 List 그려진는 동일한 순서로 표시 됩니다.The objects in this List are in the same order that they were drawn.

FingerPaintCanvasView 정의한 5 개의 메서드를 재정의 View:FingerPaintCanvasView overrides five methods defined by View:

다양 한 Touches 재정의 누적 다중선을 구성 하는 지점입니다.The various Touches overrides accumulate the points that make up the polylines.

[Draw] 완료 된 폴리라인으로 차례로 진행 다중선 재정의 그립니다.The [Draw] override draws the completed polylines and then the in-progress polylines:

public override void Draw(CGRect rect)
{
    base.Draw(rect);

    using (CGContext context = UIGraphics.GetCurrentContext())
    {
        // Stroke settings
        context.SetLineCap(CGLineCap.Round);
        context.SetLineJoin(CGLineJoin.Round);

        // Draw the completed polylines
        foreach (FingerPaintPolyline polyline in completedPolylines)
        {
            context.SetStrokeColor(polyline.Color);
            context.SetLineWidth(polyline.StrokeWidth);
            context.AddPath(polyline.Path);
            context.DrawPath(CGPathDrawingMode.Stroke);
        }

        // Draw the in-progress polylines
        foreach (FingerPaintPolyline polyline in inProgressPolylines.Values)
        {
            context.SetStrokeColor(polyline.Color);
            context.SetLineWidth(polyline.StrokeWidth);
            context.AddPath(polyline.Path);
            context.DrawPath(CGPathDrawingMode.Stroke);
        }
    }
}

각 합니다 Touches 재정의는 잠재적으로 하나 이상의 표시 하는 여러 손가락의 작업을 보고 UITouch 에 저장 된 개체는 touches 메서드의 인수입니다.Each of the Touches overrides potentially reports the actions of multiple fingers, indicated by one or more UITouch objects stored in the touches argument to the method. TouchesBegan 이러한 개체의 재정의 반복 합니다.The TouchesBegan overrides loop through these objects. UITouch 메서드를 만들고 초기화 된 새 개체 FingerPaintPolyline 에서 가져온 손가락의 초기 위치에 저장을 비롯 하 여 개체를 LocationInView 메서드.For each UITouch object, the method creates and initializes a new FingerPaintPolyline object, including storing the initial location of the finger obtained from the LocationInView method. FingerPaintPolyline 개체에 추가 됩니다는 InProgressPolylines 사용 하 여 사전을 Handle 의 속성을 UITouch 사전 키로 개체:This FingerPaintPolyline object is added to the InProgressPolylines dictionary using the Handle property of the UITouch object as a dictionary key:

public override void TouchesBegan(NSSet touches, UIEvent evt)
{
    base.TouchesBegan(touches, evt);

    foreach (UITouch touch in touches.Cast<UITouch>())
    {
        // Create a FingerPaintPolyline, set the initial point, and store it
        FingerPaintPolyline polyline = new FingerPaintPolyline
        {
            Color = StrokeColor,
            StrokeWidth = StrokeWidth,
        };

        polyline.Path.MoveToPoint(touch.LocationInView(this));
        inProgressPolylines.Add(touch.Handle, polyline);
    }
    SetNeedsDisplay();
}

메서드를 호출 하 여 마지막 SetNeedsDisplay 호출을 생성 하는 Draw 재정의 및 화면을 업데이트 합니다.The method concludes by calling SetNeedsDisplay to generate a call to the Draw override and to update the screen.

화면에 손가락이 나 손가락 이동 합니다 View 에 대 한 여러 호출을 가져옵니다 해당 TouchesMoved 재정의 합니다.As the finger or fingers move on the screen, the View gets multiple calls to its TouchesMoved override. 이 재정의 마찬가지로 반복 합니다 UITouch 에 저장 된 개체는 touches 인수 그래픽 경로에 손가락의 현재 위치를 추가 하 고:This override similarly loops through the UITouch objects stored in the touches argument and adds the current location of the finger to the graphics path:

public override void TouchesMoved(NSSet touches, UIEvent evt)
{
    base.TouchesMoved(touches, evt);

    foreach (UITouch touch in touches.Cast<UITouch>())
    {
        // Add point to path
        inProgressPolylines[touch.Handle].Path.AddLineToPoint(touch.LocationInView(this));
    }
    SetNeedsDisplay();
}

합니다 touches 컬렉션에만 UITouch 개체를 마지막으로 호출한 이후 이동 하는 손가락 TouchesBegan 또는 TouchesMoved합니다.The touches collection contains only those UITouch objects for the fingers that have moved since the last call to TouchesBegan or TouchesMoved. 해야 하는 경우 UITouch 해당 하는 개체 모든 화면 닿는 현재 손가락을 정보를 통해 제공 됩니다.는 AllTouches 속성을 UIEvent 메서드의 인수.If you ever need UITouch objects corresponding to all the fingers currently in contact with the screen, that information is available through the AllTouches property of the UIEvent argument to the method.

TouchesEnded 재정의 두 가지 작업이 있습니다.The TouchesEnded override has two jobs. 마지막 지점 전송 그래픽 경로를 추가 해야 합니다 FingerPaintPolyline 에서 개체를 inProgressPolylines 사전을 completedPolylines 목록:It must add the last point to the graphics path, and transfer the FingerPaintPolyline object from the inProgressPolylines dictionary to the completedPolylines list:

public override void TouchesEnded(NSSet touches, UIEvent evt)
{
    base.TouchesEnded(touches, evt);

    foreach (UITouch touch in touches.Cast<UITouch>())
    {
        // Get polyline from dictionary and remove it from dictionary
        FingerPaintPolyline polyline = inProgressPolylines[touch.Handle];
        inProgressPolylines.Remove(touch.Handle);

        // Add final point to path and save with completed polylines
        polyline.Path.AddLineToPoint(touch.LocationInView(this));
        completedPolylines.Add(polyline);
    }
    SetNeedsDisplay();
}

합니다 TouchesCancelled 재정의 하면 중단에 의해 처리 됩니다는 FingerPaintPolyline 사전에 있는 개체:The TouchesCancelled override is handled by simply abandoning the FingerPaintPolyline object in the dictionary:

public override void TouchesCancelled(NSSet touches, UIEvent evt)
{
    base.TouchesCancelled(touches, evt);

    foreach (UITouch touch in touches.Cast<UITouch>())
    {
        inProgressPolylines.Remove(touch.Handle);
    }
    SetNeedsDisplay();
}

이 처리를 사용 하면 모두를 핑거 페인트 프로그램 각 손가락을 추적 하 고 화면에 결과 그립니다.Altogether, this processing allows the FingerPaint program to track individual fingers and draw the results on the screen:

이제 살펴보았습니다 화면의 각 손가락을 추적 및 파일 그룹을 구분할 수 있습니다.You've now seen how you can track individual fingers on the screen and distinguish among them.