Návod – Použití dotykového ovládání v Androidu
Pojďme se podívat, jak používat koncepty z předchozí části pracovní aplikace. Vytvoříme aplikaci se čtyřmi aktivitami. První aktivitou bude nabídka nebo přepínací panel, který spustí ostatní aktivity, aby bylo možné demonstrovat různá rozhraní API. Následující snímek obrazovky ukazuje hlavní aktivitu:
První aktivita, Touch Sample, ukáže, jak používat obslužné rutiny událostí pro dotykové ovládání zobrazení. Aktivita Rozpoznávání gest předvede, jak podtřídu Android.View.Views
a zpracovat události a také ukázat, jak zpracovat gesta připnutí. Třetí a poslední aktivita, Vlastní gesto, ukáže, jak používat vlastní gesta. Abychom usnadnili sledování a absorbování věcí, rozdělíme tento názorný postup do oddílů, přičemž každá část se zaměřuje na jednu z aktivit.
Dotyková ukázková aktivita
Otevřete projekt TouchWalkthrough_Start. MainActivity je vše nastavené – je na nás, abychom implementovali dotykové chování v aktivitě. Pokud spustíte aplikaci a kliknete na Touch Sample, měla by se spustit následující aktivita:
Teď, když jsme potvrdili, že se aktivita spustí, otevřete soubor TouchActivity.cs a přidejte obslužnou rutinu události
Touch
:ImageView
_touchMeImageView.Touch += TouchMeImageViewOnTouch;
Dále přidejte následující metodu pro 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; }
Všimněte si ve výše uvedeném kódu, že zacházíme se Move
stejnou akcí a Down
akcí. Je to proto, že i když uživatel nemusí zvednout prst z prstu ImageView
, může se pohybovat kolem nebo tlak, který uživatel vyvíjí, se může změnit. Tyto typy změn vygenerují Move
akci.
Pokaždé, když se uživatel dotkne ImageView
, Touch
událost bude vyvolána a naše obslužná rutina zobrazí zprávu Touch Začíná na obrazovce, jak je znázorněno na následujícím snímku obrazovky:
Pokud se uživatel dotkne ImageView
, touch Začíná se zobrazí v sadě TextView
. Když se uživatel už nedotkne ImageView
, zobrazí se zpráva Touch Ends v sadě TextView
, jak je znázorněno na následujícím snímku obrazovky:
Aktivita rozpoznávání gest
Teď umožňuje implementovat aktivitu rozpoznávání gest. Tato aktivita předvede, jak přetáhnout zobrazení po obrazovce a ilustrovat jeden způsob implementace přiblížení připnutím.
Přidejte do aplikace novou aktivitu s názvem
GestureRecognizer
. Upravte kód pro tuto aktivitu tak, aby připomínal následující kód:public class GestureRecognizerActivity : Activity { protected override void OnCreate(Bundle bundle) { base.OnCreate(bundle); View v = new GestureRecognizerView(this); SetContentView(v); } }
Přidejte do projektu nové zobrazení Androidu a pojmenujte ho
GestureRecognizerView
. Do této třídy přidejte následující proměnné: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;
Přidejte do souboru následující konstruktor
GestureRecognizerView
. Tento konstruktor přidáImageView
do naší aktivity. V tomto okamžiku se kód stále nebude kompilovat – potřebujeme vytvořit tříduMyScaleListener
, která pomůže se změnou velikostiImageView
uživatele, když ho uživatel chytí: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)); }
Abychom nakreslili obrázek o naší aktivitě, musíme přepsat
OnDraw
metodu třídy View, jak je znázorněno v následujícím fragmentu kódu. Tento kód přesuneImageView
na pozici určenou měřítkem_posX
a_posY
také změní velikost obrázku podle faktoru škálování:protected override void OnDraw(Canvas canvas) { base.OnDraw(canvas); canvas.Save(); canvas.Translate(_posX, _posY); canvas.Scale(_scaleFactor, _scaleFactor); _icon.Draw(canvas); canvas.Restore(); }
V dalším kroku musíme aktualizovat proměnnou
_scaleFactor
instance jako uživatel p centimetryImageView
. Přidáme třídu s názvemMyScaleListener
. Tato třída bude naslouchat událostem škálování, které budou vyvolány Androidem, když uživatel strčilImageView
. Přidejte doGestureRecognizerView
souboru následující vnitřní třídu . Tato třída je .ScaleGesture.SimpleOnScaleGestureListener
Tato třída je třída pohodlí, která naslouchací procesy může podtřídět, pokud vás zajímá podmnožina gest: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; } }
Další metodou, ve
GestureRecognizerView
které musíme přepsat, jeOnTouchEvent
. Následující kód uvádí úplnou implementaci této metody. Tady je hodně kódu, takže si můžete chvilku prohlédnout a podívat se, co se tady děje. První věc, kterou tato metoda dělá, je škálovat ikonu v případě potřeby – to je zpracováno voláním_scaleDetector.OnTouchEvent
. Dále se pokusíme zjistit, jaká akce se nazývá tato metoda:Pokud se uživatel dotkne obrazovky, zaznamenáme pozice X a Y a ID prvního ukazatele, který se dotkl obrazovky.
Pokud uživatel přesunul dotykové ovládání na obrazovce, zjistíme, jak daleko uživatel ukazatel přesunul.
Pokud uživatel zvedl prst z obrazovky, zastavíme sledování gest.
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; }
Teď spusťte aplikaci a spusťte aktivitu Rozpoznávání gest. Při spuštění obrazovky by měl vypadat přibližně jako na následujícím snímku obrazovky:
Teď se dotkněte ikony a přetáhněte ji kolem obrazovky. Zkuste gesto přiblížení připnutí prstů. V určitém okamžiku může obrazovka vypadat nějak takto:
V tuto chvíli byste si měli dát pat na zadní straně: právě jste implementovali pinch-to-zoom v aplikaci pro Android! Udělejte si rychlou přestávku a můžete přejít na třetí a poslední aktivitu v tomto názorném postupu – pomocí vlastních gest.
Vlastní aktivita gest
Poslední obrazovka v tomto návodu bude používat vlastní gesta.
Pro účely tohoto návodu už byla knihovna gest vytvořená pomocí nástroje gesta a přidána do projektu v souboru Resources/raw/gestures. S tímto bitovým úklidem mimo cestu se můžete v návodu seznámit s konečnou aktivitou.
Do projektu přidejte soubor rozložení s názvem custom_gesture_layout.axml s následujícím obsahem. Projekt už má všechny obrázky ve složce Zdroje :
<?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>
Dále do projektu přidejte novou aktivitu a pojmenujte ji
CustomGestureRecognizerActivity.cs
. Přidejte do třídy dvě proměnné instance, jak ukazuje následující dva řádky kódu:private GestureLibrary _gestureLibrary; private ImageView _imageView;
OnCreate
Upravte metodu této aktivity tak, aby připomínala následující kód. Pojďme chvíli vysvětlit, co se děje v tomto kódu. První věc, kterou uděláme, je vytvoření instanceGestureOverlayView
a nastavení jako kořenového zobrazení aktivity. Také přiřadíme obslužnou rutinuGesturePerformed
události k události .GestureOverlayView
Dále nafoukneme soubor rozložení, který byl vytvořen dříve, a přidáme hoGestureOverlayView
jako podřízené zobrazení souboru . Posledním krokem je inicializace proměnné_gestureLibrary
a načtení souboru gest z prostředků aplikace. Pokud soubor gest nejde z nějakého důvodu načíst, není tato aktivita moc, takže je vypnutá: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(); } }
Poslední věc, kterou potřebujeme implementovat metodu
GestureOverlayViewOnGesturePerformed
, jak je znázorněno v následujícím fragmentu kódu.GestureOverlayView
Když zjistí gesto, volá se zpět k této metodě. První věc, kterou se snažíme získatIList<Prediction>
objekty, které odpovídají gestu voláním_gestureLibrary.Recognize()
. K získáníPrediction
nejvyššího skóre pro gesto používáme část LINQ.Pokud nedošlo k žádnému vyhovujícímu gestu s dostatečným skóre, obslužná rutina události se ukončí, aniž by cokoli udělala. V opačném případě zkontrolujeme název předpovědi a změníme zobrazený obrázek na základě názvu gesta:
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); } }
Spusťte aplikaci a spusťte aktivitu rozpoznávání vlastních gest. Měl by vypadat přibližně jako na následujícím snímku obrazovky:
Teď nakreslete na obrazovce značku zaškrtnutí a zobrazený rastrový obrázek by měl vypadat nějak takto:
Nakonec nakreslete klikybíč na obrazovce. Zaškrtávací políčko by se mělo změnit zpět na původní obrázek, jak je znázorněno na těchto snímcích obrazovky:
Teď už víte, jak integrovat dotykové ovládání a gesta v aplikaci pro Android pomocí Xamarin.Androidu.