Eventi e movimenti tocco in Xamarin.iOS

È importante comprendere gli eventi di tocco e le API di tocco in un'applicazione iOS, perché sono fondamentali per tutte le interazioni fisiche con il dispositivo. Tutte le interazioni tramite tocco comportano un UITouch oggetto . In questo articolo si apprenderà come usare la UITouch classe e le relative API per supportare il tocco. Successivamente, si espanderanno le conoscenze per imparare a supportare i movimenti.

Abilitazione del tocco

I controlli in UIKit , sottoclassati da UIControl, dipendono così dall'interazione dell'utente in cui dispongono di movimenti incorporati in UIKit e pertanto non è necessario abilitare Touch. È già abilitato.

Tuttavia, molte delle visualizzazioni in UIKit non hanno il tocco abilitato per impostazione predefinita. Esistono due modi per abilitare il tocco su un controllo. Il primo consiste nel selezionare la casella di controllo User Interaction Enabled (Interazione utente abilitata) nel riquadro delle proprietà della finestra di progettazione iOS, come illustrato nello screenshot seguente:

Check the User Interaction Enabled checkbox in the Property Pad of the iOS Designer

È anche possibile usare un controller per impostare la UserInteractionEnabled proprietà su true in una UIView classe . Questa operazione è necessaria se l'interfaccia utente viene creata nel codice.

La riga di codice seguente è un esempio:

imgTouchMe.UserInteractionEnabled = true;

Eventi di tocco

Ci sono tre fasi di tocco che si verificano quando l'utente tocca lo schermo, sposta il dito o rimuove il dito. Questi metodi sono definiti in UIResponder, ovvero la classe di base per UIView. iOS eseguirà l'override dei metodi associati in UIView e dell'oggetto per gestire il UIViewController tocco:

  • TouchesBegan : viene chiamato quando lo schermo viene toccato per la prima volta.
  • TouchesMoved : viene chiamato quando la posizione del tocco cambia quando l'utente scorre le dita intorno allo schermo.
  • TouchesEnded oppure TouchesCancelled : TouchesEnded viene chiamato quando le dita dell'utente vengono rimosse dallo schermo. TouchesCancelled viene chiamato se iOS annulla il tocco, ad esempio se un utente scorre il dito lontano da un pulsante per annullare una pressione.

Gli eventi di tocco viaggiano in modo ricorsivo verso il basso attraverso lo stack di UIViews, per verificare se l'evento di tocco si trova all'interno dei limiti di un oggetto di visualizzazione. Si tratta spesso di hit test. Verranno prima chiamati nella parte superiore UIView o UIViewController e quindi verranno chiamati su UIView e UIViewControllers sotto di essi nella gerarchia di visualizzazione.

Verrà creato un UITouch oggetto ogni volta che l'utente tocca lo schermo. L'oggetto UITouch include dati sul tocco, ad esempio quando si è verificato il tocco, dove si è verificato, se il tocco era uno scorrimento rapido e così via. Gli eventi di tocco vengono passati a una proprietà touches, che NSSet contiene uno o più tocchi. È possibile usare questa proprietà per ottenere un riferimento a un tocco e determinare la risposta dell'applicazione.

Le classi che eseguono l'override di uno degli eventi di tocco devono prima chiamare l'implementazione di base e quindi ottenere l'oggetto UITouch associato all'evento. Per ottenere un riferimento al primo tocco, chiamare la AnyObject proprietà ed eseguirne il cast come UITouch illustrato nell'esempio seguente:

public override void TouchesBegan (NSSet touches, UIEvent evt)
{
    base.TouchesBegan (touches, evt);
    UITouch touch = touches.AnyObject as UITouch;
    if (touch != null)
    {
        //code here to handle touch
    }
}

iOS riconosce automaticamente i tocco rapidi successivi sullo schermo e li raccoglierà tutti come un tocco in un singolo UITouch oggetto. In questo modo, il controllo di un doppio tocco è semplice come controllare la TapCount proprietà, come illustrato nel codice seguente:

public override void TouchesBegan (NSSet touches, UIEvent evt)
{
    base.TouchesBegan (touches, evt);
    UITouch touch = touches.AnyObject as UITouch;
    if (touch != null)
    {
        if (touch.TapCount == 2)
        {
            // do something with the double touch.
        }
    }
}

Multi-Touch

Il multitocco non è abilitato per impostazione predefinita nei controlli. Il multitocco può essere abilitato in iOS Designer, come illustrato nello screenshot seguente:

Multi-touch enabled in the iOS Designer

È anche possibile impostare il multitocco a livello di codice impostando la MultipleTouchEnabled proprietà come illustrato nella riga di codice seguente:

imgTouchMe.MultipleTouchEnabled = true;

Per determinare il numero di dita che ha toccato lo schermo, utilizzare la Count proprietà nella UITouch proprietà :

public override void TouchesBegan (NSSet touches, UIEvent evt)
{
    base.TouchesBegan (touches, evt);
    lblNumberOfFingers.Text = "Number of fingers: " + touches.Count.ToString();
}

Determinazione della posizione del tocco

Il metodo UITouch.LocationInView restituisce un oggetto CGPoint che contiene le coordinate del tocco all'interno di una determinata visualizzazione. Inoltre, è possibile verificare se tale posizione si trova all'interno di un controllo chiamando il metodo Frame.Contains. Il frammento di codice seguente mostra un esempio di questo:

if (this.imgTouchMe.Frame.Contains (touch.LocationInView (this.View)))
{
    // the touch event happened inside the UIView imgTouchMe.
}

Ora che si ha una conoscenza degli eventi di tocco in iOS, è possibile ottenere informazioni sui riconoscitori di movimento.

Riconoscitori di movimento

I riconoscitori di movimento possono semplificare e ridurre notevolmente lo sforzo di programmazione per supportare il tocco in un'applicazione. I sistemi di riconoscimento dei movimenti iOS aggregano una serie di eventi di tocco in un singolo evento di tocco.

Xamarin.iOS fornisce la classe come classe UIGestureRecognizer base per i seguenti riconoscitori di movimento predefiniti:

  • UITapGestureRecognizer : si tratta di uno o più tap.
  • UIPinchGestureRecognizer : avvicinamento delle dita e distribuzione delle dita.
  • UIPanGestureRecognizer : panoramica o trascinamento.
  • UISwipeGestureRecognizer : swiping in qualsiasi direzione.
  • UIRotationGestureRecognizer : rotazione di due dita in senso orario o in senso antiorario.
  • UILongPressGestureRecognizer : premere e tenere premuto, a volte definito pressione prolungata o clic con un clic lungo.

Il modello di base per l'uso di un riconoscimento movimento è il seguente:

  1. Creare un'istanza del riconoscimento movimento: creare prima un'istanza di una UIGestureRecognizer sottoclasse. L'oggetto di cui viene creata un'istanza verrà associato da una visualizzazione e verrà sottoposto a Garbage Collection quando la vista viene eliminata. Non è necessario creare questa vista come variabile a livello di classe.
  2. Configurare le impostazioni dei movimenti: il passaggio successivo consiste nel configurare il riconoscimento movimento. Per un elenco di proprietà che è possibile impostare per controllare il comportamento di un'istanza UIGestureRecognizer di , vedere la documentazione UIGestureRecognizer di Xamarin e le relative sottoclassi.
  3. Configurare la destinazione : a causa del relativo Objective-C patrimonio, Xamarin.iOS non genera eventi quando un riconoscimento movimento corrisponde a un movimento. UIGestureRecognizer ha un metodo , AddTarget che può accettare un delegato anonimo o un Objective-C selettore con il codice da eseguire quando il riconoscimento movimento fa una corrispondenza.
  4. Abilita riconoscimento movimenti: proprio come con gli eventi di tocco, i movimenti vengono riconosciuti solo se le interazioni tramite tocco sono abilitate.
  5. Aggiungere il riconoscimento movimento alla visualizzazione : il passaggio finale consiste nell'aggiungere il movimento a una visualizzazione chiamando View.AddGestureRecognizer e passandolo un oggetto riconoscimento movimento.

Per altre informazioni su come implementarle nel codice, vedere gli esempi di riconoscimento dei movimenti.

Quando viene chiamata la destinazione del movimento, verrà passato un riferimento al movimento che si è verificato. In questo modo, la destinazione del movimento può ottenere informazioni sul movimento che si è verificato. L'estensione delle informazioni disponibili dipende dal tipo di riconoscimento movimento usato. Per informazioni sui dati disponibili per ogni UIGestureRecognizer sottoclasse, vedere la documentazione di Xamarin.

È importante ricordare che una volta aggiunto un riconoscimento movimento a una visualizzazione, la visualizzazione (e le visualizzazioni sottostanti) non riceverà alcun evento di tocco. Per consentire eventi di tocco contemporaneamente ai movimenti, la CancelsTouchesInView proprietà deve essere impostata su false, come illustrato nel codice seguente:

_tapGesture.Recognizer.CancelsTouchesInView = false;

Ogni UIGestureRecognizer oggetto dispone di una proprietà State che fornisce informazioni importanti sullo stato del riconoscimento movimento. Ogni volta che il valore di questa proprietà cambia, iOS chiamerà il metodo di sottoscrizione fornendo un aggiornamento. Se un riconoscitore di movimenti personalizzato non aggiorna mai la proprietà State, il sottoscrittore non viene mai chiamato, rendendo inutile il riconoscimento del movimento.

I movimenti possono essere riepilogati come uno dei due tipi seguenti:

  1. Discreto: questi gesti vengono attivati solo la prima volta che vengono riconosciuti.
  2. Continuo: questi gesti continuano a essere attivati finché vengono riconosciuti.

I riconoscitori di movimento esistono in uno degli stati seguenti:

  • Possibile : questo è lo stato iniziale di tutti i riconoscitori di movimento. Si tratta del valore predefinito della proprietà State.
  • Inizio : quando viene riconosciuto per la prima volta un movimento continuo, lo stato viene impostato su Began. Ciò consente alle sottoscrizioni di distinguere tra l'avvio del riconoscimento dei movimenti e la modifica.
  • Modifica: dopo l'avvio di un movimento continuo, ma non è terminato, lo stato verrà impostato su Modificato ogni volta che un tocco si sposta o cambia, purché sia ancora all'interno dei parametri previsti del movimento.
  • Annullata : questo stato verrà impostato se il riconoscitore passa da Iniziato a Modificato e quindi i tocchi cambiano in modo tale da non adattare più il modello del movimento.
  • Riconosciuto : lo stato verrà impostato quando il riconoscimento movimento corrisponde a un set di tocchi e informerà il sottoscrittore che il movimento è terminato.
  • Terminata : alias per lo stato Riconosciuto.
  • Non riuscito : quando il riconoscimento movimento non riesce più a trovare la corrispondenza con i tocchi di ascolto, lo stato verrà modificato in Non riuscito.

Xamarin.iOS rappresenta questi valori nell'enumerazione UIGestureRecognizerState .

Uso di più movimenti

Per impostazione predefinita, iOS non consente l'esecuzione simultanea dei movimenti predefiniti. Ogni riconoscimento movimento riceverà invece eventi di tocco in un ordine non deterministico. Il frammento di codice seguente illustra come eseguire contemporaneamente un sistema di riconoscimento dei movimenti:

gesture.ShouldRecognizeSimultaneously += (UIGestureRecognizer r) => { return true; };

È anche possibile disabilitare un movimento in iOS. Esistono due proprietà delegate che consentono a un riconoscitore di movimenti di esaminare lo stato di un'applicazione e gli eventi di tocco correnti, per prendere decisioni su come e se un movimento deve essere riconosciuto. I due eventi sono:

  1. ShouldReceiveTouch : questo delegato viene chiamato subito prima che il riconoscimento movimento venga passato a un evento di tocco e offre l'opportunità di esaminare i tocchi e decidere quali tocchi verranno gestiti dal riconoscimento del movimento.
  2. ShouldBegin : viene chiamato quando un riconoscitore tenta di modificare lo stato da Possibile ad altri stati. Se viene restituito false, lo stato del riconoscimento del movimento verrà modificato in Non riuscito.

È possibile eseguire l'override di questi metodi con un delegato fortemente tipizzato UIGestureRecognizerDelegate, un delegato debole o eseguire l'associazione tramite la sintassi del gestore eventi, come illustrato nel frammento di codice seguente:

gesture.ShouldReceiveTouch += (UIGestureRecognizer r, UITouch t) => { return true; };

Infine, è possibile accodare un riconoscitore di movimenti in modo che abbia esito positivo solo se un altro riconoscimento movimento ha esito negativo. Ad esempio, un singolo riconoscimento movimento tocco dovrebbe avere esito positivo solo quando un riconoscimento movimento doppio tocco ha esito negativo. Il frammento di codice seguente fornisce un esempio di questo:

singleTapGesture.RequireGestureRecognizerToFail(doubleTapGesture);

Creazione di un movimento personalizzato

Sebbene iOS fornisca alcuni riconoscitori di movimenti predefiniti, potrebbe essere necessario creare riconoscitori di movimenti personalizzati in determinati casi. La creazione di un riconoscimento movimento personalizzato prevede i passaggi seguenti:

  1. Sottoclasse UIGestureRecognizer .
  2. Eseguire l'override dei metodi di evento di tocco appropriati.
  3. Eseguire il bubble up dello stato di riconoscimento tramite la proprietà State della classe di base.

Un esempio pratico di questo argomento verrà illustrato nella procedura dettagliata Using Touch in iOS (Uso del tocco in iOS ).