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

Compose yöntemini deneyin
Jetpack Compose, Android için önerilen kullanıcı arayüzü araç setidir. Compose'da düzenlerle nasıl çalışacağınızı öğrenin.

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ünya işlemine çok benzeyecek şekilde yanıt vermesini sağlamanız gerekir.

Uygulamanızdaki nesnelerin gerçek nesneler gibi davranmasını sağlayın. Örneğin, gerçek dünyadaki nesneler bunu yapmadığı için uygulamanızdaki resimlerin yok olup başka bir yerde yeniden görünmesine izin vermeyin. Bunun yerine, resimlerinizi bir yerden başka bir yere taşıyın.

Kullanıcılar, arayüzdeki en ufak davranışları veya hisleri bile algılar ve gerçek dünyayı taklit eden ayrıntılara en iyi tepkiyi verir. Örneğin, kullanıcılar bir kullanıcı arayüzü nesnesini hızlı kaydırdığında başlangıçta hareketi geciktiren bir atalet hissi verin. Hareketin sonunda, nesneyi fırlatmanın ötesine taşıyacak bir momentum hissi verin.

Bu sayfada, Android çerçevesinin özelliklerini kullanarak bu gerçek dünya davranışlarını özel görünümünüze nasıl ekleyeceğiniz gösterilmektedir.

İlgili ek bilgileri Giriş etkinliklerine genel bakış ve Özellik animasyonuna genel bakış başlıklı makalelerde bulabilirsiniz.

Giriş hareketlerini işleme

Android, diğer birçok kullanıcı arayüzü çerçevesi gibi bir 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 sistemindeki en yaygın giriş etkinliği dokunma'dır ve onTouchEvent(android.view.MotionEvent) tetikler. Etkinliği işlemek için bu yöntemi aşağıdaki şekilde 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 pek yararlı değildir. Modern dokunmatik kullanıcı arayüzleri, etkileşimleri dokunma, çekme, itme, fırlatma ve yakınlaştırma gibi hareketler açısından tanımlar. Android, ham dokunma etkinliklerini hareketlere dönüştürmek için GestureDetector sağlar.

GestureDetector uygulayan bir sınıfın örneğini ileterek GestureDetector.OnGestureListener oluşturun. Yalnızca birkaç hareketi işlemek istiyorsanız GestureDetector.SimpleOnGestureListener arayüzünü uygulamak yerine GestureDetector.OnGestureListener arayüzünü genişletebilirsiniz. Örneğin, bu kod, GestureDetector.SimpleOnGestureListener öğesini genişleten ve onDown(MotionEvent) öğesini 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 kullanıp kullanmadığınıza bakılmaksızın, her zaman true döndüren bir onDown() yöntemi uygulayın. Tüm hareketler onDown() mesajıyla başladığı için bu gereklidir. false değerini onDown() işlevinden GestureDetector.SimpleOnGestureListener işlevinde olduğu gibi döndürürseniz sistem, hareketin geri kalanını yoksaymak istediğinizi varsayar ve GestureDetector.OnGestureListener işlevinin diğer yöntemleri çağrılmaz. Yalnızca false değerini döndürün. Bir hareketin tamamını yoksaymak istiyorsanız onDown() değerini döndürün.

GestureDetector.OnGestureListener hizmetini uygulayıp GestureDetector.OnGestureListener örneği oluşturduktan sonra, onTouchEvent() içinde aldığınız dokunma etkinliklerini yorumlamak için GestureDetector hizmetinizi kullanabilirsiniz.GestureDetector

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

onTouchEvent() dokunma etkinliği ilettiğinizde, bu etkinlik hareketin bir parçası olarak tanınmadığı için false döndürülür. Ardından kendi özel hareket algılama kodunuzu çalıştırabilirsiniz.

Fiziksel olarak makul hareketler oluşturma

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

Örneğin, görünümde çizilen öğenin dikey ekseni etrafında dönmesini sağlayan yatay hızlı kaydırma hareketi uygulamak istediğinizi varsayalım. Bu hareket, kullanıcı arayüzü hızlı kaydırma yönünde hızlıca hareket ederek, ardından yavaşlayarak yanıt veriyorsa (kullanıcı bir volana basıp döndürüyormuş gibi) anlamlıdır.

Kaydırma hareketini animasyonla gösterme ile ilgili dokümanlarda, kendi kaydırma davranışınızı nasıl uygulayacağınız hakkında ayrıntılı bir açıklama verilmektedir. Ancak volanın hissini simüle etmek kolay değildir. Bir volan modelinin doğru çalışması için çok fazla fizik ve matematik bilgisi gerekir. Neyse ki Android, bu ve diğer davranışları simüle etmek için yardımcı sınıflar sağlar. Scroller sınıfı, flywheel tarzı hızlı kaydırma hareketlerinin işlenmesinin temelini oluşturur.

Hızlı kaydırma başlatmak için başlangıç hızıyla birlikte x ve y değerlerinin minimum ve maksimum değerlerini kullanarak fling() çağrısı yapı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ı, hızlı kaydırma hareketi için fizik modelini ayarlar. Ardından, düzenli aralıklarla Scroller.computeScrollOffset() işlevini çağırarak Scroller değerini güncelleyin. computeScrollOffset(), geçerli saati okuyarak ve o sırada x ve y konumunu hesaplamak için fizik modelini kullanarak Scroller nesnesinin dahili durumunu günceller. Bu değerleri almak için getCurrX() ve getCurrY() işlevini çağırın.

Çoğu görünüm, Scroller nesnesinin x ve y konumlarını doğrudan scrollTo()'ye iletir. 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 sorunsuz görünmesi için yeni koordinatları yeterince sık uygulayın. Bunu yapmanın iki yolu vardır:

  • fling() işlevini çağırdıktan sonra postInvalidate() işlevini çağırarak yeniden çizimi zorunlu kılın. Bu teknik, onDraw() içinde kaydırma telafilerini hesaplamanızı ve kaydırma telafisi her değiştiğinde postInvalidate() işlevini çağırmanızı gerektirir.
  • Fırlatma süresi boyunca animasyon oluşturmak için bir ValueAnimator ayarlayın ve addUpdateListener() işlevini çağırarak animasyon güncellemelerini işleyecek bir dinleyici ekleyin. Bu teknik, View özelliklerini canlandırmanıza olanak tanır.

Geçişlerinizi sorunsuz hale getirme

Kullanıcılar, modern bir kullanıcı arayüzünün durumlar arasında sorunsuz bir şekilde geçiş yapmasını bekler. Örneğin, kullanıcı arayüzü öğeleri görünmek ve kaybolmak yerine yavaş yavaş görünür ve kaybolur. Hareketler de aniden başlayıp durmak yerine sorunsuz bir şekilde başlar ve sona erer. Android özellik animasyonu çerçevesi, akıcı geçişleri kolaylaştırır.

Animasyon sistemini kullanmak için görünümünüzün görünümünü etkileyen bir özellik her değiştiğ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ümde seçilen alt bileşenin değiştirilmesi, seçilen işaretçinin ortalanması için oluşturulan görünümün tamamının döndürülmesine neden olur. ValueAnimator, yeni dönüşüm değerini hemen ayarlamak yerine birkaç yüz milisaniye içinde dönüşümü 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 özelliklerden biriyse animasyon yapmak daha da kolaydır. Çünkü görünümlerde, aşağıdaki örnekte olduğu gibi birden fazla özelliğin aynı anda 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();