Freigeben über


Exemplarische Vorgehensweise – Verwenden von Touch in Android

Sehen wir uns an, wie die Konzepte aus dem vorherigen Abschnitt in einer funktionierenden Anwendung verwendet werden. Wir erstellen eine Anwendung mit vier Aktivitäten. Die erste Aktivität ist ein Menü oder eine Übersicht, die die anderen Aktivitäten startet, um die verschiedenen APIs zu veranschaulichen. Der folgende Screenshot zeigt die Standard Aktivität:

Beispielfoto mit Touch-Me-Schaltfläche

Im ersten Aktivitätsbeispiel wird gezeigt, wie Ereignishandler zum Berühren der Ansichten verwendet werden. Die Gestenerkennungsaktivität veranschaulicht, wie Sie Unterklassen Android.View.Views und Ereignisse behandeln und wie Gesten behandelt werden. Die dritte und letzte Aktivität, benutzerdefinierte Geste, zeigt, wie benutzerdefinierte Gesten verwendet werden. Um Dies zu vereinfachen und zu absorbieren, werden wir diese exemplarische Vorgehensweise in Abschnitte unterteilen, wobei sich jeder Abschnitt auf einen der Aktivitäten konzentriert.

Touch-Beispielaktivität

  • Öffnen Sie das Projekt TouchWalkthrough_Start. Die MainActivity ist alles im Griff – es liegt an uns, das Touchverhalten in der Aktivität umzusetzen. Wenn Sie die Anwendung ausführen und auf "Touchbeispiel" klicken, sollte die folgende Aktivität gestartet werden:

    Screenshot der Aktivität mit angezeigten Fingereingaben

  • Nachdem wir nun bestätigt haben, dass die Aktivität gestartet wird, öffnen Sie die Datei TouchActivity.cs , und fügen Sie einen Handler für das Touch Ereignis der ImageView:

    _touchMeImageView.Touch += TouchMeImageViewOnTouch;
    
  • Fügen Sie als Nächstes die folgende Methode zum TouchActivity.cs hinzu:

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

Beachten Sie im obigen Code, dass wir die und Down die Move Aktion genauso behandeln. Dies liegt daran, dass sich der Benutzer, auch wenn er den Finger nicht vom Finger hebt ImageView, sich bewegen kann oder der vom Benutzer ausgeübte Druck geändert werden kann. Diese Arten von Änderungen generieren eine Move Aktion.

Jedes Mal, wenn der Benutzer das ImageViewEreignis berührt, wird das Touch Ereignis ausgelöst, und unser Handler zeigt die Meldung "Touch Begins " auf dem Bildschirm an, wie im folgenden Screenshot gezeigt:

Screenshot der Aktivität mit

Solange der Benutzer die ImageViewFingereingabe berührt, wird "Touch Begins " im TextViewBereich angezeigt. Wenn der Benutzer die ImageViewFingereingabe nicht mehr berührt, wird die Meldung "Touch Ends " im TextViewfolgenden Screenshot angezeigt:

Screenshot der Aktivität mit Touch-Ends

Gestikerkennungsaktivität

Ermöglicht jetzt die Implementierung der Gestenerkennungsaktivität. Diese Aktivität veranschaulicht, wie Sie eine Ansicht um den Bildschirm ziehen und eine Möglichkeit zum Implementieren des Zusammendrückens zum Zoomen veranschaulichen.

  • Fügen Sie der Anwendung eine neue Aktivität hinzu, die aufgerufen wird GestureRecognizer. Bearbeiten Sie den Code für diese Aktivität so, dass er dem folgenden Code ähnelt:

    public class GestureRecognizerActivity : Activity
    {
        protected override void OnCreate(Bundle bundle)
        {
            base.OnCreate(bundle);
            View v = new GestureRecognizerView(this);
            SetContentView(v);
        }
    }
    
  • Fügen Sie dem Projekt eine neue Android-Ansicht hinzu, und nennen Sie sie GestureRecognizerView. Fügen Sie dieser Klasse die folgenden Variablen hinzu:

    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;
    
  • Fügen Sie den folgenden Konstruktor zu GestureRecognizerView. Dieser Konstruktor fügt unserer Aktivität einen ImageView hinzu. An diesem Punkt wird der Code immer noch nicht kompiliert – wir müssen die Klasse MyScaleListener erstellen, die beim Zusammendrücken der ImageView Größe des Benutzers hilft:

    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));
    }
    
  • Um das Bild für unsere Aktivität zu zeichnen, müssen wir die OnDraw Methode der View-Klasse außer Kraft setzen, wie im folgenden Codeausschnitt gezeigt. Dieser Code verschebt die ImageView position, die durch _posX und _posY ändert die Größe des Bilds entsprechend dem Skalierungsfaktor:

    protected override void OnDraw(Canvas canvas)
    {
        base.OnDraw(canvas);
        canvas.Save();
        canvas.Translate(_posX, _posY);
        canvas.Scale(_scaleFactor, _scaleFactor);
        _icon.Draw(canvas);
        canvas.Restore();
    }
    
  • Als Nächstes müssen wir die Instanzvariable _scaleFactor aktualisieren, während der Benutzer die ImageView. Wir fügen eine Klasse mit dem Namen MyScaleListenerhinzu. Diese Klasse lauscht auf die Skalierungsereignisse, die von Android ausgelöst werden, wenn der Benutzer die ImageView. Fügen Sie die folgende innere Klasse zu GestureRecognizerView. Diese Klasse ist ein ScaleGesture.SimpleOnScaleGestureListener. Diese Klasse ist eine Komfortklasse, die Listener unterklassen können, wenn Sie an einer Teilmenge von Gesten interessiert sind:

    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;
        }
    }
    
  • Die nächste Methode, in GestureRecognizerView der wir außer Kraft setzen müssen, ist OnTouchEvent. Der folgende Code listet die vollständige Implementierung dieser Methode auf. Hier gibt es viel Code, also lassen Sie sich eine Minute dauern und sehen, was hier passiert. Als Erstes skaliert diese Methode das Symbol bei Bedarf – dies wird durch Aufrufen _scaleDetector.OnTouchEventbehandelt. Als Nächstes versuchen wir herauszufinden, welche Aktion diese Methode aufgerufen hat:

    • Wenn der Benutzer den Bildschirm berührt hat, zeichnen wir die X- und Y-Position und die ID des ersten Zeigers auf, der den Bildschirm berührt hat.

    • Wenn der Benutzer seine Toucheingabe auf dem Bildschirm bewegt hat, stellen wir fest, wie weit der Benutzer den Zeiger bewegt hat.

    • Wenn der Benutzer seinen Finger vom Bildschirm entfernt hat, beenden wir die Nachverfolgung der Gesten.

    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;
    }
    
  • Führen Sie nun die Anwendung aus, und starten Sie die Gestenerkennungsaktivität. Wenn der Bildschirm gestartet wird, sollte etwa wie der folgende Screenshot aussehen:

    Startbildschirm der Gestenerkennung mit Android-Symbol

  • Tippen Sie nun auf das Symbol, und ziehen Sie es um den Bildschirm. Probieren Sie die Zusammendrücken-zu-Zoom-Geste aus. Irgendwann sieht der Bildschirm ungefähr wie der folgende Screenshot aus:

    Bewegungssymbol um den Bildschirm

An dieser Stelle sollten Sie sich einen Paten auf den Rücken geben: Sie haben gerade Zusammendrücken in einer Android-Anwendung implementiert! Machen Sie eine kurze Pause und können sie in dieser exemplarischen Vorgehensweise mit benutzerdefinierten Gesten zur dritten und endgültigen Aktivität wechseln.

Benutzerdefinierte Gestenaktivität

Der letzte Bildschirm in dieser exemplarischen Vorgehensweise verwendet benutzerdefinierte Gesten.

Für diese exemplarische Vorgehensweise wurde die Gestenbibliothek bereits mithilfe des Gestiktools erstellt und dem Projekt in den Dateiressourcen /Roh-/Gesten hinzugefügt. Mit diesem Stück Haushaltung aus dem Weg können Sie mit der endgültigen Aktivität in der exemplarischen Vorgehensweise loswerden.

  • Fügen Sie dem Projekt eine Layoutdatei mit dem Namen custom_gesture_layout.axml mit dem folgenden Inhalt hinzu. Das Projekt verfügt bereits über alle Bilder im Ordner "Ressourcen ":

    <?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>
    
  • Fügen Sie dem Projekt als Nächstes eine neue Aktivität hinzu, und nennen Sie sie CustomGestureRecognizerActivity.cs. Fügen Sie der Klasse zwei Instanzenvariablen hinzu, wie in den folgenden beiden Codezeilen dargestellt:

    private GestureLibrary _gestureLibrary;
    private ImageView _imageView;
    
  • Bearbeiten Sie die OnCreate Methode dieser Aktivität so, dass sie dem folgenden Code ähnelt. Lassen Sie uns eine Minute dauern, um zu erläutern, was in diesem Code passiert. Als Erstes instanziieren wir eine GestureOverlayView Instanziierung und legen sie als Stammansicht der Aktivität fest. Außerdem weisen wir dem GesturePerformed Ereignis eines GestureOverlayViewEreignisses einen Ereignishandler zu. Als Nächstes wird die zuvor erstellte Layoutdatei aufgeblasen und als untergeordnete Ansicht der GestureOverlayViewDatei hinzugefügt. Der letzte Schritt besteht darin, die Variable _gestureLibrary zu initialisieren und die Gestendatei aus den Anwendungsressourcen zu laden. Wenn die Gestendatei aus irgendeinem Grund nicht geladen werden kann, gibt es nicht viel dieser Aktivität, sodass sie heruntergefahren wird:

    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();
        }
    }
    
  • Abschließend müssen wir die Methode GestureOverlayViewOnGesturePerformed implementieren, wie im folgenden Codeausschnitt gezeigt. Wenn die GestureOverlayView Geste erkannt wird, ruft sie diese Methode zurück. Als Erstes versuchen wir, objekte IList<Prediction> abzurufen, die mit der Geste übereinstimmen, indem wir aufrufen _gestureLibrary.Recognize(). Wir verwenden ein bisschen LINQ, um die Prediction höchste Punktzahl für die Geste zu erhalten.

    Wenn keine Übereinstimmungsgeste mit einer hohen Punktzahl vorhanden ist, wird der Ereignishandler beendet, ohne etwas zu tun. Andernfalls überprüfen wir den Namen der Vorhersage und ändern das angezeigte Bild basierend auf dem Namen der Geste:

    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);
        }
    }
    
  • Führen Sie die Anwendung aus, und starten Sie die Aktivität "Benutzerdefinierte Gestenerkennung". Es sollte ungefähr wie der folgende Screenshot aussehen:

    Screenshot mit Bild

    Zeichnen Sie nun ein Häkchen auf dem Bildschirm, und die angezeigte Bitmap sollte ungefähr wie in den nächsten Screenshots dargestellt aussehen:

    Gezeichnetes Häkchen, Häkchen wird erkannt

    Zeichnen Sie schließlich einen Skizzenausschnitt auf dem Bildschirm. Das Kontrollkästchen sollte wie in den folgenden Screenshots dargestellt wieder in das ursprüngliche Bild geändert werden:

    Skizze auf dem Bildschirm, originales Bild wird angezeigt

Sie wissen jetzt, wie Sie Toucheingaben und Gesten in eine Android-Anwendung mit Xamarin.Android integrieren.