Procedura dettagliata - Uso del tocco in Android
Vediamo come usare i concetti della sezione precedente in un'applicazione funzionante. Verrà creata un'applicazione con quattro attività. La prima attività sarà un menu o uno switchboard che avvierà le altre attività per illustrare le varie API. Lo screenshot seguente mostra l'attività principale:
La prima attività, Touch Sample, mostrerà come usare i gestori eventi per toccare le visualizzazioni. L'attività Riconoscimento movimento illustra come sottoclassare Android.View.Views
e gestire eventi, nonché come gestire i movimenti di avvicinamento delle dita. La terza e ultima attività, Custom Gesture, mostrerà come usare i movimenti personalizzati. Per semplificare il completamento e l'assorbimento, questa procedura dettagliata verrà suddivisa in sezioni, con ogni sezione incentrata su una delle attività.
Attività di esempio tocco
Aprire il TouchWalkthrough_Start del progetto. MainActivity è tutto pronto per andare– spetta a noi implementare il comportamento di tocco nell'attività. Se si esegue l'applicazione e si fa clic su Touch Sample, l'attività seguente dovrebbe essere avviata:
Ora che è stato confermato che l'attività viene avviata, aprire il file TouchActivity.cs e aggiungere un gestore per l'evento
Touch
diImageView
:_touchMeImageView.Touch += TouchMeImageViewOnTouch;
Aggiungere quindi il metodo seguente a TouchActivity.cs:
private void TouchMeImageViewOnTouch(object sender, View.TouchEventArgs touchEventArgs) { string message; switch (touchEventArgs.Event.Action & MotionEventActions.Mask) { case MotionEventActions.Down: case MotionEventActions.Move: message = "Touch Begins"; break; case MotionEventActions.Up: message = "Touch Ends"; break; default: message = string.Empty; break; } _touchInfoTextView.Text = message; }
Si noti nel codice precedente che l'azione Move
e Down
viene considerata come la stessa. Ciò è dovuto al fatto che anche se l'utente potrebbe non sollevare il dito dall'oggetto ImageView
, può muoversi o la pressione esercitata dall'utente può cambiare. Questi tipi di modifiche genereranno un'azione Move
.
Ogni volta che l'utente tocca , ImageView
l'evento Touch
verrà generato e il gestore visualizzerà il messaggio Touch Begins sullo schermo, come illustrato nello screenshot seguente:
Finché l'utente tocca , il ImageView
tocco inizia verrà visualizzato in TextView
. Quando l'utente non tocca ImageView
più , il messaggio Touch Ends verrà visualizzato in TextView
, come illustrato nello screenshot seguente:
Attività riconoscimento movimenti
Ora consente di implementare l'attività Riconoscimento movimento. Questa attività illustra come trascinare una visualizzazione sullo schermo e illustrare un modo per implementare il avvicinamento delle dita allo zoom.
Aggiungere una nuova attività all'applicazione denominata
GestureRecognizer
. Modificare il codice per questa attività in modo che sia simile al codice seguente:public class GestureRecognizerActivity : Activity { protected override void OnCreate(Bundle bundle) { base.OnCreate(bundle); View v = new GestureRecognizerView(this); SetContentView(v); } }
Aggiungere una nuova visualizzazione Android al progetto e denominarla
GestureRecognizerView
. Aggiungere le variabili seguenti a questa classe:private static readonly int InvalidPointerId = -1; private readonly Drawable _icon; private readonly ScaleGestureDetector _scaleDetector; private int _activePointerId = InvalidPointerId; private float _lastTouchX; private float _lastTouchY; private float _posX; private float _posY; private float _scaleFactor = 1.0f;
Aggiungere il costruttore seguente a
GestureRecognizerView
. Questo costruttore aggiungerà un oggetto all'attivitàImageView
. A questo punto il codice non verrà ancora compilato: è necessario creare la classeMyScaleListener
che consentirà di ridimensionareImageView
quando l'utente lo avvicina:public GestureRecognizerView(Context context): base(context, null, 0) { _icon = context.Resources.GetDrawable(Resource.Drawable.Icon); _icon.SetBounds(0, 0, _icon.IntrinsicWidth, _icon.IntrinsicHeight); _scaleDetector = new ScaleGestureDetector(context, new MyScaleListener(this)); }
Per disegnare l'immagine sull'attività, è necessario eseguire l'override del
OnDraw
metodo della classe View, come illustrato nel frammento di codice seguente. Questo codice sposta l'oggettoImageView
nella posizione specificata da_posX
e_posY
ridimensiona l'immagine in base al fattore di ridimensionamento:protected override void OnDraw(Canvas canvas) { base.OnDraw(canvas); canvas.Save(); canvas.Translate(_posX, _posY); canvas.Scale(_scaleFactor, _scaleFactor); _icon.Draw(canvas); canvas.Restore(); }
Successivamente è necessario aggiornare la variabile
_scaleFactor
di istanza quando l'utente avvicina .ImageView
Verrà aggiunta una classe denominataMyScaleListener
. Questa classe sarà in ascolto degli eventi di scalabilità che verranno generati da Android quando l'utente avvicina .ImageView
Aggiungere la classe interna seguente aGestureRecognizerView
. Questa classe è un oggettoScaleGesture.SimpleOnScaleGestureListener
. Questa classe è una classe utile che i listener possono sottoclasse quando si è interessati a un subset di movimenti:private class MyScaleListener : ScaleGestureDetector.SimpleOnScaleGestureListener { private readonly GestureRecognizerView _view; public MyScaleListener(GestureRecognizerView view) { _view = view; } public override bool OnScale(ScaleGestureDetector detector) { _view._scaleFactor *= detector.ScaleFactor; // put a limit on how small or big the image can get. if (_view._scaleFactor > 5.0f) { _view._scaleFactor = 5.0f; } if (_view._scaleFactor < 0.1f) { _view._scaleFactor = 0.1f; } _view.Invalidate(); return true; } }
Il metodo successivo in cui è necessario eseguire l'override
GestureRecognizerView
èOnTouchEvent
. Il codice seguente elenca l'implementazione completa di questo metodo. C'è un sacco di codice qui, quindi si può prendere un minuto e guardare cosa sta succedendo qui. La prima cosa che questo metodo esegue è ridimensionare l'icona, se necessario. Questa operazione viene gestita chiamando_scaleDetector.OnTouchEvent
. Successivamente si tenta di capire quale azione ha chiamato questo metodo:Se l'utente ha toccato lo schermo, registriamo le posizioni X e Y e l'ID del primo puntatore che ha toccato lo schermo.
Se l'utente ha spostato il tocco sullo schermo, si scoprirà quanto l'utente ha spostato il puntatore.
Se l'utente ha sollevato il dito dallo schermo, interromperemo il rilevamento dei movimenti.
public override bool OnTouchEvent(MotionEvent ev) { _scaleDetector.OnTouchEvent(ev); MotionEventActions action = ev.Action & MotionEventActions.Mask; int pointerIndex; switch (action) { case MotionEventActions.Down: _lastTouchX = ev.GetX(); _lastTouchY = ev.GetY(); _activePointerId = ev.GetPointerId(0); break; case MotionEventActions.Move: pointerIndex = ev.FindPointerIndex(_activePointerId); float x = ev.GetX(pointerIndex); float y = ev.GetY(pointerIndex); if (!_scaleDetector.IsInProgress) { // Only move the ScaleGestureDetector isn't already processing a gesture. float deltaX = x - _lastTouchX; float deltaY = y - _lastTouchY; _posX += deltaX; _posY += deltaY; Invalidate(); } _lastTouchX = x; _lastTouchY = y; break; case MotionEventActions.Up: case MotionEventActions.Cancel: // We no longer need to keep track of the active pointer. _activePointerId = InvalidPointerId; break; case MotionEventActions.PointerUp: // check to make sure that the pointer that went up is for the gesture we're tracking. pointerIndex = (int) (ev.Action & MotionEventActions.PointerIndexMask) >> (int) MotionEventActions.PointerIndexShift; int pointerId = ev.GetPointerId(pointerIndex); if (pointerId == _activePointerId) { // This was our active pointer going up. Choose a new // action pointer and adjust accordingly int newPointerIndex = pointerIndex == 0 ? 1 : 0; _lastTouchX = ev.GetX(newPointerIndex); _lastTouchY = ev.GetY(newPointerIndex); _activePointerId = ev.GetPointerId(newPointerIndex); } break; } return true; }
Eseguire ora l'applicazione e avviare l'attività Riconoscimento movimento. All'avvio della schermata dovrebbe essere simile allo screenshot seguente:
Toccare ora l'icona e trascinarla sullo schermo. Provare il movimento di avvicinamento delle dita allo zoom. A un certo punto la schermata potrebbe essere simile alla schermata seguente:
A questo punto dovresti darti una pat sulla schiena: hai appena implementato il avvicinamento delle dita per ingrandire un'applicazione Android! Fare una pausa rapida e consente di passare alla terza e ultima attività in questa procedura dettagliata, usando movimenti personalizzati.
Attività movimento personalizzata
La schermata finale di questa procedura dettagliata userà movimenti personalizzati.
Ai fini di questa procedura dettagliata, la libreria di movimenti è già stata creata usando lo strumento movimento e aggiunta al progetto nel file Resources/raw/gestures. Con questo po ' di pulizia fuori dal modo, consente di iniziare con l'attività finale nella procedura dettagliata.
Aggiungere un file di layout denominato custom_gesture_layout.axml al progetto con il contenuto seguente. Il progetto include già tutte le immagini nella cartella Risorse :
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <LinearLayout android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" /> <ImageView android:src="@drawable/check_me" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="3" android:id="@+id/imageView1" android:layout_gravity="center_vertical" /> <LinearLayout android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" /> </LinearLayout>
Aggiungere quindi una nuova attività al progetto e denominarla
CustomGestureRecognizerActivity.cs
. Aggiungere due variabili di istanza alla classe , come illustrato nelle due righe di codice seguenti:private GestureLibrary _gestureLibrary; private ImageView _imageView;
Modificare il
OnCreate
metodo dell'attività in modo che sia simile al codice seguente. Consente di dedicare qualche minuto a spiegare cosa sta succedendo in questo codice. La prima cosa che facciamo è creare un'istanzaGestureOverlayView
di e impostarne una come visualizzazione radice dell'attività. Viene inoltre assegnato un gestore eventi all'eventoGesturePerformed
diGestureOverlayView
. Successivamente, si gonfia il file di layout creato in precedenza e lo si aggiunge come visualizzazione figlio dell'oggettoGestureOverlayView
. Il passaggio finale consiste nell'inizializzare la variabile_gestureLibrary
e caricare il file dei movimenti dalle risorse dell'applicazione. Se il file di movimenti non può essere caricato per qualche motivo, non è possibile eseguire molte operazioni di questo tipo di attività, in modo da arrestare:protected override void OnCreate(Bundle bundle) { base.OnCreate(bundle); GestureOverlayView gestureOverlayView = new GestureOverlayView(this); SetContentView(gestureOverlayView); gestureOverlayView.GesturePerformed += GestureOverlayViewOnGesturePerformed; View view = LayoutInflater.Inflate(Resource.Layout.custom_gesture_layout, null); _imageView = view.FindViewById<ImageView>(Resource.Id.imageView1); gestureOverlayView.AddView(view); _gestureLibrary = GestureLibraries.FromRawResource(this, Resource.Raw.gestures); if (!_gestureLibrary.Load()) { Log.Wtf(GetType().FullName, "There was a problem loading the gesture library."); Finish(); } }
L'ultima operazione da eseguire per implementare il metodo
GestureOverlayViewOnGesturePerformed
, come illustrato nel frammento di codice seguente.GestureOverlayView
Quando rileva un movimento, viene chiamato a questo metodo. La prima cosa che si tenta di ottenere unIList<Prediction>
oggetto che corrisponde al movimento chiamando_gestureLibrary.Recognize()
. Per ottenere ilPrediction
punteggio più alto per il movimento viene usato un po' di LINQ.Se non è presente alcun movimento corrispondente con un punteggio sufficientemente alto, il gestore eventi viene chiuso senza eseguire alcuna operazione. In caso contrario, controlliamo il nome della stima e modifichiamo l'immagine visualizzata in base al nome del movimento:
private void GestureOverlayViewOnGesturePerformed(object sender, GestureOverlayView.GesturePerformedEventArgs gesturePerformedEventArgs) { IEnumerable<Prediction> predictions = from p in _gestureLibrary.Recognize(gesturePerformedEventArgs.Gesture) orderby p.Score descending where p.Score > 1.0 select p; Prediction prediction = predictions.FirstOrDefault(); if (prediction == null) { Log.Debug(GetType().FullName, "Nothing seemed to match the user's gesture, so don't do anything."); return; } Log.Debug(GetType().FullName, "Using the prediction named {0} with a score of {1}.", prediction.Name, prediction.Score); if (prediction.Name.StartsWith("checkmark")) { _imageView.SetImageResource(Resource.Drawable.checked_me); } else if (prediction.Name.StartsWith("erase", StringComparison.OrdinalIgnoreCase)) { // Match one of our "erase" gestures _imageView.SetImageResource(Resource.Drawable.check_me); } }
Eseguire l'applicazione e avviare l'attività Riconoscimento movimento personalizzato. Dovrebbe essere simile allo screenshot seguente:
Disegnare ora un segno di spunta sullo schermo e la bitmap visualizzata dovrebbe essere simile a quella mostrata negli screenshot successivi:
Infine, disegnare una scarabocchia sullo schermo. La casella di controllo deve tornare all'immagine originale, come illustrato negli screenshot seguenti:
Si ha ora una conoscenza di come integrare il tocco e i movimenti in un'applicazione Android usando Xamarin.Android.