Sdílet prostřednictvím


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:

Ukázkový snímek obrazovky s tlačítkem Touch Me

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:

    Snímek obrazovky s aktivitou se zobrazeným dotykovým ovládáním

  • 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:

Snímek obrazovky s aktivitou Zahájení dotykového ovládání

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:

Snímek obrazovky s aktivitou s dotykovými konci

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řídu MyScaleListener , která pomůže se změnou velikosti ImageView 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řesune ImageView 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 centimetry ImageView. Přidáme třídu s názvem MyScaleListener. Tato třída bude naslouchat událostem škálování, které budou vyvolány Androidem, když uživatel strčil ImageView. Přidejte do GestureRecognizerViewsouboru 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, je OnTouchEvent. 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:

    Úvodní obrazovka rozpoznávání gest s ikonou Androidu

  • 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:

    Ikona pohybu gest po obrazovce

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í instance GestureOverlayView a nastavení jako kořenového zobrazení aktivity. Také přiřadíme obslužnou rutinu GesturePerformed události k události .GestureOverlayView Dále nafoukneme soubor rozložení, který byl vytvořen dříve, a přidáme ho GestureOverlayViewjako 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ískat IList<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:

    Snímek obrazovky s obrázkem Zkontrolovat mě

    Teď nakreslete na obrazovce značku zaškrtnutí a zobrazený rastrový obrázek by měl vypadat nějak takto:

    Nakreslená značka zaškrtnutí, značka zaškrtnutí je rozpoznána.

    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:

    Klikybíč na obrazovce, zobrazí se původní obrázek.

Teď už víte, jak integrovat dotykové ovládání a gesta v aplikaci pro Android pomocí Xamarin.Androidu.