Oluşturma ile tek elle yapılan hareketler


Wear OS 7 (API düzeyi 37) ve sonraki sürümlerde, tek elle hareket çerçevesi ve Wear OS için Compose'un bir parçası olan bir API sayesinde kullanıcılar uygulamanızla dokunmadan etkileşime geçebilir.

Başlangıçta Pixel Watch cihazlarda (Pixel Watch 3 ve sonraki modeller) desteklenen bu çerçeve, tüm OEM'ler tarafından kullanılabilir. Bu API'yi kullanmaya başladığınızda, donanım desteği genişledikçe uygulamanızın hareket desteği ekosistem genelinde otomatik olarak ölçeklenir.

Wear OS çerçevesi, kullanıcıların mevcut hareketleri kullanıcı arayüzünü karıştırmadan keşfetmesine yardımcı olmak için animasyonlu hareket göstergeleri sunar. Bu görsel ipuçları, hareketin nerede yapılabileceğini vurgularken sistem, kullanıcının tercihlerine göre gösterim sıklığını ve sessize alma sıklığını otomatik olarak yönetir.

Desteklenen hareketler ve işlemler

Wear OS hareket çerçevesi iki hareket türünü destekler:

  • Birincil işlem (Çift parmakla sıkıştırma): Ekranda yapılan ana işlemle (ör. aramayı yanıtlama veya medya oynatmayı açma/kapatma) eşlenir.
  • İşlemi kapatma (bileği çevirme): Geriye doğru gezinme, iletişim kutusunu kapatma veya istemi iptal etme işlemlerini yapar.

Compose'da hareketleri yapılandırma

Tek elle hareketler API'si kullanıcı arayüzünüzü iyileştirebilse de bazı donanımların ve OEM'lerin bu hareketleri desteklemediğini unutmamak önemlidir. API, uygulamanızın bu desteklenmeyen cihazlardan birinde çalıştığını algılarsa kitaplık, standart dokunma etkileşimlerini etkilemeden otomatik olarak işlem yapmaz.

Standart Compose davranışlarında olduğu gibi, kullanıcı arayüzü öğelerinde tek elle yapılan hareketleri değiştiriciler kullanarak etkinleştirirsiniz. Uygulamanızın hareketlerini, gerçekleştirilecek işleme (birincil veya kapatma) ve gestureId'ya göre yapılandırarak ipucu görüntüleme sıklığı ve frekansın kapatılması gibi sistem düzeyindeki kullanıcı tercihlerine uygun hale getirebilirsiniz. Bu yapılandırmayı bir OneHandedGestureConfiguration nesnesi oluşturarak ifade edersiniz. Bu nesneyi oluşturmak için rememberOneHandedGestureConfiguration işlevini kullanmanızı öneririz. OneHandedGestureConfiguration, hareket önceliğini de belirleyebileceğiniz yerdir.

rememberOneHandedGestureConfiguration işlevi, uygulama durumunu açığa çıkarmadan yeniden oluşturmalar genelinde kullanıcı etkileşimi geçmişini izler. Uygulamanız yapılandırmayı oluşturduktan sonra, yapılandırmayı etkileşimli composable'ınızdaki Modifier.oneHandedGesture öğesine iletmelidir.

Kitaplık, kullanıcıların kullanılabilir hareketleri keşfetmesine yardımcı olmak için OneHandedGestureClickIndicator yöntemini sağlar. Bu yöntem, alttaki içeriğini değiştirerek kullanıcıya bir hareket işleminin kullanılabileceğini bildiren bir sarmalayıcı görevi görür.

Etkileşimli bileşenler

Düğme gibi etkileşimli bir kontrolde hareketleri etkinleştirmek için OneHandedGestureAction.Primary belirten bir yapılandırma oluşturun ve oneHandedGesture değiştiricisini uygulayın. Hareket etkinliklerinin kontrol üzerinde görsel basma geri bildirimi vermesi için hem kontrol hem de değiştiriciye aynı MutableInteractionSource değerini iletin.

Hareket göstergesini etkinleştirmek için OneHandedGestureClickIndicatorState örneği oluşturup hatırlayın. Ardından, görsel geri bildirimi tetiklemek için showIndicator işlevini oneHandedGesture değiştiricisi tarafından sağlanan onGestureAvailable geri arama işlevi içinde çağırın. Bu, sisteme bir belirtme etkinliğinin gerçekleştiğini bildirir. Çağrıldığında bileşen, normal içeriğini kısa bir süre için hareket animasyonuyla değiştirir.

var isPlaying by remember { mutableStateOf(false) }
val onClick = { isPlaying = !isPlaying }

val gestureConfig = rememberOneHandedGestureConfiguration(
    action = OneHandedGestureAction.Primary
)
val indicatorState = remember { OneHandedGestureClickIndicatorState() }
val coroutineScope = rememberCoroutineScope()
val interactionSource = remember { MutableInteractionSource() }

Button(
    onClick = onClick,
    interactionSource = interactionSource,
    modifier = Modifier
        .fillMaxWidth()
        .oneHandedGesture(
            gestureConfiguration = gestureConfig,
            interactionSource = interactionSource,
            onGestureLabel = if (isPlaying) "pause" else "play",
            onGestureAvailable = { coroutineScope.launch { indicatorState.showIndicator() } },
            onGesture = onClick
        )
) {
    OneHandedGestureClickIndicator(
        gestureConfiguration = gestureConfig,
        state = indicatorState
    ) {
        Text(if (isPlaying) "Pause" else "Play", modifier = Modifier.fillMaxWidth())
    }
}

Kaydırılabilir kapsayıcılar

Kaydırılabilir ekranlar veya listeler için OneHandedGestureAction.Primary belirten bir yapılandırma oluşturun ve oneHandedGesture değiştiricisini kapsayıcınıza uygulayarak scrollDown gibi bir kaydırma yardımcısı çağırın.

Kaydırma işlemleriyle ilgili görsel geri bildirim sağlamak için OneHandedGestureScrollIndicator simgesini kullanabilirsiniz. Bu bileşen, kaydırma konumunu gösteren standart bir kaydırma göstergesi olarak işlev görür ancak kullanıcının kaydırma hareketi yapabileceğini de belirtebilir. Bu gösterge genellikle bir ScreenScaffold öğesinin scrollIndicator yuvasına iletilir ve TransformingLazyColumn gibi kaydırılabilir bir kapsayıcının durumuyla birlikte kullanılır. Ayrıca görsel geçişlerini yönetmek için OneHandedGestureScrollIndicatorState değerini de gözlemler.

Görsel geri bildirimi tetiklemek için bu durumda showIndicator işlevini çağırın. Bu işlev genellikle oneHandedGesture değiştiricisinin onGestureAvailable geri çağırma işlevinin içinde yer alır. Tetiklendikten sonra gösterge, kullanıcıyı uyarmak için standart görsel durumunu geçici olarak bir hareket animasyonu dizisiyle değiştirir.

val scrollState = rememberTransformingLazyColumnState()
val gestureConfig = rememberOneHandedGestureConfiguration(
    action = OneHandedGestureAction.Primary,
    priority = OneHandedGesturePriority.Scrollable
)
val indicatorState = remember(gestureConfig) { OneHandedGestureScrollIndicatorState() }
val coroutineScope = rememberCoroutineScope()

ScreenScaffold(
    scrollState = scrollState,
    scrollIndicator = {
        OneHandedGestureScrollIndicator(
            gestureConfiguration = gestureConfig,
            indicatorState = indicatorState,
            scrollState = scrollState,
            modifier = Modifier.align(Alignment.CenterEnd)
        )
    }
) { contentPadding ->
    TransformingLazyColumn(
        state = scrollState,
        contentPadding = contentPadding,
        modifier = Modifier
            .fillMaxSize()
            .oneHandedGesture(
                gestureConfiguration = gestureConfig,
                onGestureLabel = "scroll",
                onGestureAvailable = {
                    coroutineScope.launch { indicatorState.showIndicator() }
                },
                onGesture = { OneHandedGestureDefaults.scrollDown(scrollState) }
            )
    ) {
        items(10) { index ->
            Text("Item $index", modifier = Modifier.padding(8.dp))
        }
    }
}

Birden fazla hareketi birleştirme

gesturePriority öğenize OneHandedGestureConfiguration ekleyerek hem kaydırma hem de tıklama hareketini aynı birincil işlemle yapılandırabilirsiniz:

  • OneHandedGesturePriority.Clickable (en yüksek): Ekranda göründüklerinde hareketleri yakalayabilmeleri için Button veya Card türündeki etkileşimli kontrollere atayın.
  • OneHandedGesturePriority.Scrollable (orta): Tıklanabilir alt öğelere izin verecek ancak tıklanabilir kontrol görünmediğinde kaydırılacak şekilde kaydırılabilir veya sayfalandırılabilir kapsayıcılara atayın.
  • OneHandedGesturePriority.Unspecified (en düşük): Öncelik atanmamış. Bu, priority ayarlanmamış bir hareketin varsayılan değeridir.

priority = OneHandedGesturePriority.Clickable değerini bir iç düğmede ve priority = OneHandedGesturePriority.Scrollable değerini üst listede açıkça ayarlayarak sistemin bu hareket önceliği davranışını göstermesini sağlayabilirsiniz. Kullanıcı, tek elle hareketle birincil işlemi tetiklediğinde önce liste, düğme görünene kadar aşağı kaydırılır, ardından düğmenin tıklama işlemi yakalanır.

ADB ile hareketleri test etme ve hatalarını ayıklama

Android Debug Bridge (adb) ve IWearGestureService sistem hizmetini kullanarak fiziksel bilek hareketleri yapmadan fiziksel bir cihazda veya emülatörde tek elle hareketleri test edebilirsiniz.

Hareket simülasyonunu etkinleştirme

ADB kullanarak hareketleri simüle etmeden önce cihaz ayarlarınızı ve kısıtlama geçersiz kılmalarınızı yapılandırın:

  1. Wear OS cihazınızda Wear OS 7 (API düzeyi 37) veya sonraki bir sürümün yüklü olduğunu doğrulayın:

    adb shell getprop ro.build.version.sdk
    
  2. Bileğinizde olmayan veya şarj cihazında duran fiziksel bir cihazda test yapıyorsanız hareket çerçevesinin etkin kalması için vücut dışı kısıtlamayı geçersiz kılın:

    adb shell cmd IWearGestureService override-constraints offbody-state
    

ADB kullanarak hareket etkinliklerini tetikleme

İki kez sıkıştırma hareketini (Pixel Watch'taki Primary işlemi) simüle etmek için aşağıdaki ADB kabuk komutunu çalıştırın:

adb shell cmd IWearGestureService gesture DoublePinch

Bileği çevirme hareketini (Pixel Watch'taki Dismiss işlemi) simüle etmek için aşağıdaki ADB kabuk komutunu çalıştırın:

adb shell cmd IWearGestureService gesture WristTurn

Hareket ipucu izlemeyi sıfırlama

Sistem, kullanıcı etkileşimi geçmişini izler ve genel sıklık ayarına (ör. Her zaman veya Günlük) göre kayan hareket ipuçları gösterir. Uygulamanızın hareket göstergelerinde hata ayıklarken bu izleme geçmişini sıfırlayın. Böylece paketiniz için ipuçları tekrar gösterilir:

  • userdebug derlemelerinde veya emülatörlerde:

    adb shell cmd IWearGestureService hint clear <your_package_name>
    
  • Perakende (user) derlemelerinde:

    Root erişimi olmayan ticari cihazlarda hint clear, sistem izinleri tarafından engellenir. İpucu keşfini sıfırlamak için uygulamanın yerel verilerini temizleyin:

    adb shell pm clear <your_package_name>
    

Varsayılan kısıtlamaları geri yükleme

Testi tamamladığınızda tüm hata ayıklama kısıtlaması geçersiz kılmalarını sıfırlamak için:

adb shell cmd IWearGestureService override-constraints reset

Hareket ekleme sorunlarını giderme

Uygulamanız simüle edilmiş hareketleri almıyorsa:

  1. Kol saati ekranının uyanık ve AÇIK olduğundan emin olun. Hareket çerçevesi, ekran kapalıyken veya ortam modundayken hareketleri uygulamalara göndermez. ADB'yi kullanarak ekranı uyandırmak için şu komutu çalıştırın:

    adb shell input keyevent KEYCODE_WAKEUP
    
  2. Uygulamanızın etkin hareket abonesi olarak kaydedilip kaydedilmediğini ve şu anda pencere odağını elinde tutup tutmadığını kontrol edin:

    adb shell cmd IWearGestureService get-active-gestures -readable
    

    Uygulamanızın hareket ekranı ön planda olduğunda ve ekran uyanıkken bu komut [DoublePinch] veya [DoublePinch, WristTurn] değerini döndürür. Boş bir liste ([]) döndürülürse pencerenizin odaklanıp odaklanmadığını veya vücut dışı kısıtlamaların etkinleştirmeyi engelleyip engellemediğini kontrol edin.

  3. Dahili hareket hizmeti durumunu ve etkin abone jetonlarını inceleyin:

    adb shell dumpsys IWearGestureService
    

Ek kaynaklar

Tek el hareketlerinin ne zaman ve nerede kullanılacağıyla ilgili tasarım rehberliği için Tek el hareketleri başlıklı makaleyi inceleyin.