다음을 통해 공유


Xamarin.iOS의 멀티 터치 손가락 추적

이 문서에서는 여러 손가락에서 터치 이벤트를 추적하는 방법을 보여 줍니다.

멀티 터치 애플리케이션이 화면에서 동시에 이동할 때 개별 손가락을 추적해야 하는 경우가 있습니다. 일반적인 애플리케이션 중 하나는 손가락 페인트 프로그램입니다. 사용자가 한 손가락으로 그릴 수 있을 뿐만 아니라 한 번에 여러 손가락으로 그릴 수도 있습니다. 프로그램에서 여러 터치 이벤트를 처리할 때 이러한 손가락을 구분해야 합니다.

손가락이 화면을 처음 터치하면 iOS에서 해당 손가락에 대한 개체를 UITouch 만듭니다. 이 개체는 화면에서 손가락을 이동한 다음 화면에서 들어올려 개체가 삭제되는 시점과 동일하게 기본. 손가락을 추적하려면 프로그램에서 이 UITouch 개체를 직접 저장하지 않아야 합니다. 대신 형식 IntPtr 의 속성을 사용하여 Handle 이러한 UITouch 개체를 고유하게 식별할 수 있습니다.

거의 항상 개별 손가락을 추적하는 프로그램은 터치 추적을 위한 사전을 기본. iOS 프로그램의 경우 사전 키는 특정 손가락을 식별하는 값입니다 Handle . 사전 값은 애플리케이션에 따라 달라집니다. 샘플 프로그램에서 각 손가락 스트로크(터치에서 해제)는 해당 손가락으로 그린 선을 렌더링하는 데 필요한 모든 정보를 포함하는 개체와 연결됩니다. 이 프로그램은 이 목적을 위해 작은 FingerPaintPolyline 클래스를 정의합니다.

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 개체가 그려질 때 선의 여러 점을 누적하고 렌더링할 수 있습니다.

아래에 표시된 코드의 나머지 모든 항목은 명명FingerPaintCanvasView된 파생 항목에 UIView 포함되어 있습니다. 이 클래스는 기본 하나 이상의 손가락으로 적극적으로 그려지는 동안 형식 FingerPaintPolyline 개체의 사전을 포함합니다.

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

이 사전을 사용하면 개체의 속성 UITouchHandle 따라 각 손가락과 연결된 정보를 빠르게 가져올 FingerPaintPolyline 수 있습니다.

또한 클래스는 FingerPaintCanvasView 완료된 폴리라인에 대한 개체를 기본.List

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

List 개체의 개체는 그렸던 순서와 같습니다.

FingerPaintCanvasView 는 다음으로 정의된 View5개의 메서드를 재정의합니다.

다양한 Touches 재정의는 폴리라인을 구성하는 점을 누적합니다.

[Draw] 재정의는 완성된 폴리라인과 진행 중인 폴리라인을 그립니다.

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 보고할 수 있습니다. 재정의는 TouchesBegan 이러한 개체를 반복합니다. 각 UITouch 개체에 대해 메서드는 메서드에서 LocationInView 가져온 손가락의 초기 위치를 저장하는 것을 포함하여 새 FingerPaintPolyline 개체를 만들고 초기화합니다. 이 FingerPaintPolyline 개체는 개체의 InProgressPolylinesUITouch 속성을 사전 키로 사용하여 Handle 사전에 추가됩니다.

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

메서드는 재정의에 대한 호출을 생성하고 화면을 업데이트하기 위해 Draw 호출 SetNeedsDisplay 하여 종료됩니다.

손가락 또는 손가락이 화면에서 이동하면 재정의 View 에 대한 여러 호출을 TouchesMoved 가져옵니다. 이 재정의는 인수에 touches 저장된 개체를 UITouch 반복하고 그래픽 경로에 손가락의 현재 위치를 추가합니다.

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 마지막 호출 TouchesBegan 이후 이동한 손가락에 대한 개체만 UITouch 포함됩니다TouchesMoved. 현재 화면과 접촉하는 모든 손가락에 해당하는 개체가 필요한 UITouch 경우 해당 정보는 메서드에 대한 인수의 UIEvent 속성을 통해 AllTouches 사용할 수 있습니다.

재정의에는 TouchesEnded 두 개의 작업이 있습니다. 그래픽 경로에 마지막 점을 추가하고 사전에서 목록으로 개체를 inProgressPolylinescompletedPolylines 전송 FingerPaintPolyline 해야 합니다.

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 중단하여 처리됩니다.

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

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

이 처리를 통해 샘플 프로그램은 개별 손가락을 추적하고 화면에 결과를 그릴 수 있습니다.

개별 손가락 추적 및 화면에 결과 그리기

이제 화면에서 개별 손가락을 추적하고 구분하는 방법을 살펴보았습니다.