İzlenecek yol - Android'de Touch'ı kullanma

Çalışan bir uygulamanın önceki bölümünde yer alan kavramların nasıl kullanılacağını görelim. Dört etkinliği olan bir uygulama oluşturacağız. İlk etkinlik, çeşitli API'leri göstermek için diğer etkinlikleri başlatan bir menü veya geçiş panosu olacaktır. Aşağıdaki ekran görüntüsünde ana etkinlik gösterilmektedir:

Bana Dokun düğmesiyle örnek ekran görüntüsü

İlk Etkinlik olan Dokunma Örneği, Görünümler'e dokunmak için olay işleyicilerinin nasıl kullanılacağını gösterir. Hareket Tanıma etkinliği, olayları alt sınıflama Android.View.Views ve işlemenin yanı sıra sıkıştırma hareketlerinin nasıl işleneceğini gösterir. Üçüncü ve son etkinlik olan Özel Hareket, özel hareketlerin nasıl kullanıldığını gösterir. İşlerin daha kolay izlenip emilmesini sağlamak için, bu kılavuzu bölümlere ayıracağız ve her bölüm Etkinlikler'in birine odaklanacak.

Dokunma Örneği Etkinliği

  • Proje TouchWalkthrough_Start açın. MainActivity her şeyi yapmaya hazır – etkinlikte dokunma davranışını uygulamak bize bağlı. Uygulamayı çalıştırıp Dokunma Örneği'ne tıklarsanız aşağıdaki etkinliğin başlatılması gerekir:

    Dokunma Başlar'ın görüntülendiği etkinliğin ekran görüntüsü

  • Etkinliğin başlatıldığını onayladığımıza göre, TouchActivity.cs dosyasını açın ve olayı ImageViewiçin Touch bir işleyici ekleyin:

    _touchMeImageView.Touch += TouchMeImageViewOnTouch;
    
  • Ardından, TouchActivity.cs aşağıdaki yöntemi ekleyin:

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

Yukarıdaki kodda ve Down eylemini Move aynı şekilde ele aldığımıza dikkat edin. Bunun nedeni, kullanıcının parmağından kaldıramasa ImageViewda hareket edebilir veya kullanıcı tarafından uygulanan baskı değişebilir. Bu tür değişiklikler bir Move eylem oluşturur.

Kullanıcı öğesine her dokunduğunda ImageViewolay tetiklenir ve işleyicimiz, aşağıdaki ekran görüntüsünde gösterildiği gibi Dokunma Başlar iletisini ekranda görüntüler:Touch

Dokunma Başlangıcı ile etkinliğin ekran görüntüsü

Kullanıcı öğesine dokunduğu ImageViewsürece, Dokunma Başlar içinde TextViewgörüntülenir. Kullanıcı artık öğesine dokunmadığındaImageView, aşağıdaki ekran görüntüsünde TextViewgösterildiği gibi Dokunma Uçları iletisi içinde görüntülenir:

Dokunmatik Uçlarla etkinliğin ekran görüntüsü

Hareket Tanıma Etkinliği

Şimdi Hareket Tanıma etkinliğini uygulayalım. Bu etkinlik, ekranın çevresinde bir görünümün nasıl sürükleneceğini ve sıkıştırma-yakınlaştırmanın tek bir yolunun nasıl gösterileceğini gösterir.

  • Uygulamaya adlı GestureRecognizeryeni bir Etkinlik ekleyin. Bu etkinliğin kodunu, aşağıdaki koda benzeyecek şekilde düzenleyin:

    public class GestureRecognizerActivity : Activity
    {
        protected override void OnCreate(Bundle bundle)
        {
            base.OnCreate(bundle);
            View v = new GestureRecognizerView(this);
            SetContentView(v);
        }
    }
    
  • Projeye yeni bir Android görünümü ekleyin ve olarak adlandırın GestureRecognizerView. Bu sınıfa aşağıdaki değişkenleri ekleyin:

    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;
    
  • aşağıdaki oluşturucuyu öğesine GestureRecognizerViewekleyin. Bu oluşturucu etkinliğimize bir ImageView ekler. Bu noktada kod yine derlenmez; kullanıcı sıkıştırdığında yeniden boyutlandırmaya ImageView yardımcı olacak sınıfı MyScaleListener oluşturmamız gerekir:

    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));
    }
    
  • Resmi etkinliğimize çizmek için aşağıdaki kod parçacığında gösterildiği gibi View sınıfının yöntemini geçersiz kılmamız OnDraw gerekir. Bu kod, ImageView öğesini tarafından _posX belirtilen konuma taşır ve _posY ölçeklendirme faktörüne göre görüntüyü yeniden boyutlandıracaktır:

    protected override void OnDraw(Canvas canvas)
    {
        base.OnDraw(canvas);
        canvas.Save();
        canvas.Translate(_posX, _posY);
        canvas.Scale(_scaleFactor, _scaleFactor);
        _icon.Draw(canvas);
        canvas.Restore();
    }
    
  • Daha sonra kullanıcı sıkıştırması ile örnek değişkenini _scaleFactorImageViewgüncelleştirmemiz gerekir. adlı MyScaleListenerbir sınıf ekleyeceğiz. Bu sınıf, kullanıcı tarafından sıkıştırıldığında Android tarafından tetiklenecek ölçek olaylarını ImageViewdinler. Aşağıdaki iç sınıfı öğesine GestureRecognizerViewekleyin. Bu sınıf bir ScaleGesture.SimpleOnScaleGestureListener. Bu sınıf, hareketlerin bir alt kümesiyle ilgilendiğinizde dinleyicilerin alt sınıf oluşturabileceği bir kolaylık sınıfıdır:

    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;
        }
    }
    
  • içinde geçersiz kılmamız GestureRecognizerView gereken bir sonraki yöntem: OnTouchEvent. Aşağıdaki kod, bu yöntemin tam uygulamasını listeler. Burada çok fazla kod var, bu nedenle bir dakikanızı alıp burada neler olduğuna bakalım. Bu yöntemin yaptığı ilk şey gerekirse simgeyi ölçeklendirmektir; bu, çağrılarak _scaleDetector.OnTouchEventişlenir. Daha sonra bu yöntemi çağıran eylemi bulmaya çalışacağız:

    • Kullanıcı ekrana ile dokunduysa, X ve Y konumlarını ve ekrana dokunan ilk işaretçinin kimliğini kaydederiz.

    • Kullanıcı ekranda dokunuşunu taşıdıysa, kullanıcının işaretçiyi ne kadar hareket ettirdiğini anlarız.

    • Kullanıcı parmağını ekrandan kaldırdıysa hareketleri izlemeyi durdururuz.

    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;
    }
    
  • Şimdi uygulamayı çalıştırın ve Hareket Tanıma etkinliğini başlatın. Ekran başlatıldığında aşağıdaki ekran görüntüsüne benzer olmalıdır:

    Android simgesiyle Hareket Tanıma başlangıç ekranı

  • Şimdi simgeye dokunun ve ekranın çevresinde sürükleyin. Sıkıştırma-yakınlaştırma hareketini deneyin. Bir noktada ekranınız aşağıdaki ekran görüntüsüne benzer olabilir:

    Hareketler ekranda hareket etme simgesi

Bu noktada kendinize sırt üstü bir pat vermelisiniz: Bir Android uygulamasında sıkıştırma-yakınlaştırmayı yeni uyguladınız! Hızlı bir mola verin ve özel hareketleri kullanarak bu kılavuzda üçüncü ve son Etkinliğe geçelim.

Özel Hareket Etkinliği

Bu kılavuzdaki son ekranda özel hareketler kullanılır.

Bu İzlenecek Yol'un amaçları doğrultusunda hareket kitaplığı, Hareket Aracı kullanılarak zaten oluşturulmuş ve Kaynaklar/ham/hareketler dosyasında projeye eklenmiştir. Bu temizlik parçasının aradan çıkmasıyla, izlenecek yoldaki son Etkinlik'e geçelim.

  • Projeye aşağıdaki içeriklerle custom_gesture_layout.axml adlı bir düzen dosyası ekleyin. Projenin kaynaklar klasöründeki tüm görüntüler zaten var:

    <?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>
    
  • Ardından projeye yeni bir Etkinlik ekleyin ve adını verin CustomGestureRecognizerActivity.cs. Aşağıdaki iki kod satırı içinde gösterildiği gibi sınıfına iki örnek değişkeni ekleyin:

    private GestureLibrary _gestureLibrary;
    private ImageView _imageView;
    
  • OnCreate Bu Etkinliğin yöntemini aşağıdaki koda benzeyecek şekilde düzenleyin. Bu kodda neler olduğunu açıklamak için bir dakikanızı alalım. İlk olarak bir GestureOverlayView örneği oluşturup bunu Etkinliğin kök görünümü olarak ayarlayacağız. Ayrıca olayına GesturePerformed bir olay işleyicisi GestureOverlayViewatarız. Ardından daha önce oluşturulan düzen dosyasını şişirir ve bunu öğesinin GestureOverlayViewalt görünümü olarak ekleriz. Son adım, değişkeni _gestureLibrary başlatmak ve uygulama kaynaklarından hareketler dosyasını yüklemektir. Hareketler dosyası bir nedenden dolayı yüklenemiyorsa, bu Etkinliğin gerçekleştirebileceği pek bir şey yoktur, bu nedenle kapatılır:

    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();
        }
    }
    
  • Aşağıdaki kod parçacığında gösterildiği gibi yöntemini GestureOverlayViewOnGesturePerformed uygulamamız gereken son şey. GestureOverlayView bir hareket algıladığında, bu yönteme geri çağırır. çağrısı yaparak _gestureLibrary.Recognize()hareketle eşleşen bir IList<Prediction> nesne almaya çalışacağımız ilk şey. Hareket için en yüksek puana sahip olanı almak Prediction için biraz LINQ kullanırız.

    Yeterli puana sahip eşleşen bir hareket yoksa olay işleyicisi hiçbir şey yapmadan çıkar. Aksi takdirde, tahminin adını denetler ve görüntülenen görüntüyü hareketin adına göre değiştiririz:

    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);
        }
    }
    
  • Uygulamayı çalıştırın ve Özel Hareket Tanıma etkinliğini başlatın. Aşağıdaki ekran görüntüsüne benzer olmalıdır:

    Beni Denetle resminin ekran görüntüsü

    Şimdi ekrana bir onay işareti çizin ve görüntülenen bit eşlem sonraki ekran görüntülerinde gösterilene benzer olmalıdır:

    Çizilmiş onay işareti, onay işareti tanındı

    Son olarak, ekrana bir karalama çizin. Onay kutusu, şu ekran görüntülerinde gösterildiği gibi özgün görüntüsüne geri dönmelidir:

    Ekranda karalama, özgün görüntü görüntülenir

Artık Xamarin.Android kullanarak bir Android uygulamasında dokunma ve hareketleri tümleştirme hakkında bilgi sahibisiniz.