Sdílet prostřednictvím


Sledování vícedotykových prstů v Xamarin.iOS

Tento dokument ukazuje, jak sledovat dotykové události z více prstů.

Existují časy, kdy aplikace pro vícedotykové ovládání potřebuje sledovat jednotlivé prsty, když se pohybují současně na obrazovce. Jednou z typických aplikací je program malování prstem. Chcete, aby uživatel mohl kreslit jedním prstem, ale také kreslit více prsty najednou. Když program zpracovává více dotykových událostí, musí rozlišovat mezi těmito prsty.

Když se prst poprvé dotkne obrazovky, vytvoří UITouch iOS objekt pro tento prst. Tento objekt zůstává stejný jako prst se pohybuje na obrazovce a potom se zvedne z obrazovky, v jakém okamžiku se objekt odstraní. Chcete-li sledovat prsty, program by se měl vyhnout uložení tohoto UITouch objektu přímo. Místo toho může použít Handle vlastnost typu IntPtr k jedinečné identifikaci těchto UITouch objektů.

Téměř vždy program, který sleduje jednotlivé prsty, udržuje slovník pro sledování dotykového ovládání. V případě programu pro iOS je klíč slovníku Handle hodnotou, která identifikuje konkrétní prst. Hodnota slovníku závisí na aplikaci. V ukázkovém programu je každý tah prstem (od dotykového do uvolnění) přidružený k objektu, který obsahuje všechny informace potřebné k vykreslení čáry kreslené tímto prstem. Program definuje malou FingerPaintPolyline třídu pro tento účel:

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

    public CGColor Color { set; get; }

    public float StrokeWidth { set; get; }

    public CGPath Path { private set; get; }
}

Každá křivka má barvu, šířku tahu a grafický CGPath objekt pro iOS pro kumulování a vykreslení více bodů čáry při vykreslení.

Veškerý zbytek níže uvedeného kódu je obsažen v derivátu UIView s názvem FingerPaintCanvasView. Tato třída udržuje slovník objektů typu FingerPaintPolyline během doby, kdy jsou aktivně kresleny jedním nebo více prsty:

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

Tento slovník umožňuje zobrazení rychle získat FingerPaintPolyline informace spojené s každým prstem na Handle základě vlastnosti objektu UITouch .

Třída FingerPaintCanvasView také udržuje List objekt pro křivky, které byly dokončeny:

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

Objekty v tomto List pořadí jsou ve stejném pořadí, v jakém byly nakresleny.

FingerPaintCanvasView přepíše pět metod definovaných View:

Různé Touches přepsání hromadí body, které tvoří křivky.

Přepsání [Draw] nakreslí dokončené čáry a pak probíhající čáry:

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

Každá z Touches přepsání potenciálně hlásí akce více prstů označené jedním nebo více UITouch objekty uloženými v touches argumentu metody. Přepsání TouchesBegan prochází těmito objekty. Pro každý UITouch objekt vytvoří a inicializuje nový FingerPaintPolyline objekt, včetně uložení počátečního umístění prstu získaného LocationInView z metody. Tento FingerPaintPolyline objekt je přidán do InProgressPolylines slovníku Handle pomocí vlastnosti UITouch objektu jako klíč slovníku:

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

Metoda končí voláním SetNeedsDisplay pro vygenerování volání přepsání Draw a aktualizací obrazovky.

Při pohybu prstem nebo prsty na obrazovce View získá více volání k TouchesMoved přepsání. Toto přepsání UITouch podobným způsobem prochází objekty uložené v argumentu touches a přidá aktuální umístění prstu do grafické cesty:

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

Kolekce touches obsahuje pouze objekty UITouch pro prsty, které se přesunuly od posledního volání nebo TouchesBeganTouchesMoved. Pokud někdy potřebujete UITouch objekty odpovídající všem prstům aktuálně v kontaktu s obrazovkou, jsou informace k dispozici prostřednictvím AllTouches vlastnosti UIEvent argumentu pro metodu.

Přepsání TouchesEnded má dvě úlohy. Musí přidat poslední bod do grafické cesty a přenést FingerPaintPolyline objekt ze inProgressPolylines slovníku completedPolylines do seznamu:

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

Přepsání TouchesCancelled se zpracovává jednoduše opuštěním objektu FingerPaintPolyline ve slovníku:

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

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

Toto zpracování celkem umožňuje ukázkovém programu sledovat jednotlivé prsty a kreslit výsledky na obrazovce:

Sledování jednotlivých prstů a kreslení výsledků na obrazovce

Teď jste viděli, jak můžete sledovat jednotlivé prsty na obrazovce a rozlišovat mezi nimi.