Özel bir görünümü etkileşimli hale getirme

Oluşturma yöntemini deneyin
Jetpack Compose, Android için önerilen kullanıcı arayüzü araç setidir. Compose'da düzenlerle çalışma hakkında bilgi edinin.

Kullanıcı arayüzü çizmek, özel görünüm oluşturmanın yalnızca bir parçasıdır. Ayrıca görünümünüzün, kullanıcı girişine, taklit ettiğiniz gerçek dünyadaki eyleme çok benzeyen yanıt vermesini de sağlamalısınız.

Uygulamanızdaki nesnelerin gerçek nesneler gibi davranmasını sağlayın. Örneğin, uygulamanızdaki görüntülerin ortadan kalkıp başka bir yerde görünmesine izin vermeyin. Gerçek dünyadaki nesneler bunu yapmaz. Bunun yerine resimlerinizi bir yerden başka bir yere taşıyın.

Kullanıcılar bir arayüzde fark edilmeyen davranışları veya hisleri bile saptar ve en iyi gerçek dünyayı taklit eden inceliklere tepki verirler. Örneğin, kullanıcılar bir kullanıcı arayüzü nesnesini hızla salladığında, başlangıçta onlara hareketi geciktiren bir atalet hissi verin. Hareketin sonunda, onlara nesneyi kaçış hareketinin ötesine taşıyan bir momentum kazandırın.

Bu sayfada, gerçek dünyadaki bu davranışları özel görünümünüze eklemek için Android çerçevesinin özelliklerinin nasıl kullanılacağı gösterilmektedir.

İlgili ek bilgileri Giriş etkinliklerine genel bakış ve Mülk animasyonuna genel bakış bölümlerinde bulabilirsiniz.

Giriş hareketlerini işleme

Diğer birçok kullanıcı arayüzü çerçevesi gibi Android de giriş etkinliği modelini destekler. Kullanıcı işlemleri, geri çağırmaları tetikleyen etkinliklere dönüşür ve uygulamanızın kullanıcıya nasıl yanıt vereceğini özelleştirmek için geri çağırmaları geçersiz kılabilirsiniz. Android sisteminde en yaygın giriş etkinliği, onTouchEvent(android.view.MotionEvent) tetikleyen dokunma etkinliğidir. Etkinliği işlemek için bu yöntemi aşağıdaki gibi geçersiz kılın:

Kotlin

override fun onTouchEvent(event: MotionEvent): Boolean {
    return super.onTouchEvent(event)
}

Java

@Override
   public boolean onTouchEvent(MotionEvent event) {
    return super.onTouchEvent(event);
   }

Dokunma etkinlikleri tek başına çok kullanışlı bir yöntem değildir. Modern dokunmatik kullanıcı arayüzleri, dokunma, çekme, itme, sallama ve yakınlaştırma gibi hareketlerle etkileşimleri tanımlar. Android, ham dokunma etkinliklerini harekete dönüştürmek için GestureDetector özelliğini sunar.

GestureDetector.OnGestureListener uygulayan bir sınıfın bir örneğini geçirerek bir GestureDetector oluşturun. Yalnızca birkaç hareketi işlemek istiyorsanız GestureDetector.OnGestureListener arayüzünü uygulamak yerine GestureDetector.SimpleOnGestureListener hareketini genişletebilirsiniz. Örneğin, bu kod GestureDetector.SimpleOnGestureListener öğesini genişleten ve onDown(MotionEvent) değerini geçersiz kılan bir sınıf oluşturur.

Kotlin

private val myListener =  object : GestureDetector.SimpleOnGestureListener() {
    override fun onDown(e: MotionEvent): Boolean {
        return true
    }
}

private val detector: GestureDetector = GestureDetector(context, myListener)

Java

class MyListener extends GestureDetector.SimpleOnGestureListener {
   @Override
   public boolean onDown(MotionEvent e) {
       return true;
   }
}
detector = new GestureDetector(getContext(), new MyListener());

GestureDetector.SimpleOnGestureListener kullansanız da kullanmasanız da her zaman true döndüren bir onDown() yöntemi uygulayın. Tüm hareketler bir onDown() mesajıyla başladığından bu gereklidir. onDown() kaynağından false değerini (GestureDetector.SimpleOnGestureListener) döndürürseniz sistem, hareketin geri kalanını yoksaymak istediğinizi varsayar ve diğer GestureDetector.OnGestureListener yöntemleri çağrılmaz. Bir hareketin tamamını yoksaymak istiyorsanız yalnızca onDown() öğesinden false değerini döndürün.

GestureDetector.OnGestureListener kodunu uyguladıktan ve GestureDetector örneği oluşturduktan sonra, onTouchEvent() ile aldığınız dokunma etkinliklerini yorumlamak için GestureDetector öğenizi kullanabilirsiniz.

Kotlin

override fun onTouchEvent(event: MotionEvent): Boolean {
    return detector.onTouchEvent(event).let { result ->
        if (!result) {
            if (event.action == MotionEvent.ACTION_UP) {
                stopScrolling()
                true
            } else false
        } else true
    }
}

Java

@Override
public boolean onTouchEvent(MotionEvent event) {
   boolean result = detector.onTouchEvent(event);
   if (!result) {
       if (event.getAction() == MotionEvent.ACTION_UP) {
           stopScrolling();
           result = true;
       }
   }
   return result;
}

Bir hareketin parçası olarak tanımadığı bir dokunma etkinliğini onTouchEvent() ilettiğinizde false sonucunu döndürür. Daha sonra kendi özel hareket algılama kodunuzu çalıştırabilirsiniz.

Fiziksel olarak inandırıcı bir hareket oluşturma

Hareketler dokunmatik ekranlı cihazları kontrol etmenin güçlü bir yoludur, ancak fiziksel olarak makul sonuçlar üretmedikleri sürece sezgisel olmayan ve hatırlamaları zor olabilir.

Örneğin, görünümde çizilen öğeyi kendi dikey ekseninde dönen bir yatay kaydırma hareketi uygulamak istediğinizi varsayalım. Kullanıcı bir çarkı itip döndürüyormuş gibi kullanıcı arayüzün hızlı bir şekilde kaçış yönünde hareket edip sonra yavaşlayarak yanıt verdiği durumlarda bu hareket anlamlıdır.

Kaydırma hareketini canlandırma ile ilgili dokümanlar, kendi kaydırma davranışınızı nasıl uygulayacağınız hakkında ayrıntılı bir açıklama sunar. Ancak volan hissini simüle etmek hiç de kolay değil. Volan modelinin doğru çalışması için çok fazla fizik ve matematik gerekir. Neyse ki Android, bu ve diğer davranışları simüle etmek için yardımcı sınıflar sunar. Volan tarzı hızla sallanma hareketlerini işlemenin temeli Scroller sınıfıdır.

Bir kaçış başlatmak için fling() yöntemini, başlangıç hızıyla ve kaçış işleminin minimum ve maksimum x ve y değerleriyle birlikte çağırın. Hız değeri için GestureDetector tarafından hesaplanan değeri kullanabilirsiniz.

Kotlin

fun onFling(e1: MotionEvent, e2: MotionEvent, velocityX: Float, velocityY: Float): Boolean {
    scroller.fling(
            currentX,
            currentY,
            (velocityX / SCALE).toInt(),
            (velocityY / SCALE).toInt(),
            minX,
            minY,
            maxX,
            maxY
    )
    postInvalidate()
    return true
}

Java

@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
   scroller.fling(currentX, currentY, velocityX / SCALE, velocityY / SCALE, minX, minY, maxX, maxY);
   postInvalidate();
    return true;
}

fling() çağrısı, kısa hareket için fizik modelini ayarlar. Daha sonra düzenli aralıklarla Scroller.computeScrollOffset() çağırarak Scroller uygulamasını güncelleyin. computeScrollOffset(), geçerli saati okuyarak ve fizik modelini kullanarak o andaki x ile y konumunu hesaplayarak Scroller nesnenin iç durumunu günceller. Bu değerleri almak için getCurrX() ve getCurrY() numaralarını arayın.

Çoğu görünüm, Scroller nesnesinin x ve y konumlarını doğrudan scrollTo() öğesine aktarır. Bu örnek biraz farklıdır: Görünümün dönme açısını ayarlamak için mevcut kaydırma x konumunu kullanır.

Kotlin

scroller.apply {
    if (!isFinished) {
        computeScrollOffset()
        setItemRotation(currX)
    }
}

Java

if (!scroller.isFinished()) {
    scroller.computeScrollOffset();
    setItemRotation(scroller.getCurrX());
}

Scroller sınıfı, kaydırma konumlarını sizin için hesaplar ancak bu konumları görünümünüze otomatik olarak uygulamaz. Kaydırma animasyonunun yumuşak görünmesini sağlayacak kadar yeni koordinatları uygulayın. Bunu yapmanın iki yolu vardır:

  • fling() çağrısından sonra postInvalidate() yöntemini çağırarak yeniden çizim yapılmasını zorunlu kılın. Bu teknik, onDraw() içinde kaydırma ofsetlerini hesaplamanızı ve kaydırma ofseti her değiştiğinde postInvalidate() yöntemini çağırmanızı gerektirir.
  • Hızlı kaydırma süresi boyunca animasyon uygulamak için bir ValueAnimator ayarlayın ve addUpdateListener() yöntemini çağırarak animasyon güncellemelerini işlemek için bir işleyici ekleyin. Bu teknik, bir View öğesinin özelliklerini canlandırmanızı sağlar.

Sorunsuz geçişler yapın

Kullanıcılar, modern bir kullanıcı arayüzünün durumlar arasında sorunsuz bir şekilde geçiş yapmasını bekler: Kullanıcı arayüzü öğelerinin görünüp kaybolmak yerine kararması ve kaybolması, hareketler aniden başlayıp durması yerine akıcı bir şekilde başlayıp sona ermesi. Android özellik animasyon çerçevesi, yumuşak geçişleri kolaylaştırır.

Animasyon sistemini kullanmak için bir özellik görünümünüzün görünümünü etkileyen unsurları değiştirdiğinde özelliği doğrudan değiştirmeyin. Bunun yerine, değişikliği yapmak için ValueAnimator kullanın. Aşağıdaki örnekte, görünümdeki seçili alt bileşenin değiştirilmesi, oluşturulan görünümün tamamının döndürülerek seçim işaretçisinin ortalanmasını sağlar. ValueAnimator, yeni rotasyon değerini hemen ayarlamak yerine birkaç yüz milisaniyelik bir süre boyunca dönüşü değiştirir.

Kotlin

autoCenterAnimator = ObjectAnimator.ofInt(this, "Rotation", 0).apply {
    setIntValues(targetAngle)
    duration = AUTOCENTER_ANIM_DURATION
    start()
}

Java

autoCenterAnimator = ObjectAnimator.ofInt(this, "Rotation", 0);
autoCenterAnimator.setIntValues(targetAngle);
autoCenterAnimator.setDuration(AUTOCENTER_ANIM_DURATION);
autoCenterAnimator.start();

Değiştirmek istediğiniz değer temel View özelliklerinden biriyse animasyonu gerçekleştirmek daha da kolaylaşır çünkü görünümlerde, aşağıdaki örnekte olduğu gibi birden çok mülkün eş zamanlı animasyonu için optimize edilmiş yerleşik bir ViewPropertyAnimator bulunur:

Kotlin

animate()
    .rotation(targetAngle)
    .duration = ANIM_DURATION
    .start()

Java

animate().rotation(targetAngle).setDuration(ANIM_DURATION).start();