Manajemen gerakan: menangani konflik isyarat. Bagian 3

Terjemahan artikel disiapkan sebelum peluncuran kursus pengembangan Android tingkat lanjut dan dasar .



Ini adalah artikel ketiga dalam seri tentang kontrol gerakan. Anda dapat membiasakan diri dengan terjemahan bagian pertama dan kedua jika Anda melewatkannya.

Pada artikel sebelumnya, kami membahas topik mengisi ruang layar dari ujung ke ujung. Pada artikel ini, kita akan melihat bagaimana menangani konflik yang muncul antara gerakan aplikasi Anda dan gerakan sistem baru di Android 10 .

Apa yang kita maksud dengan konflik isyarat? Mari kita lihat sebuah contoh. Katakanlah kita memiliki pemutar musik yang memungkinkan pengguna untuk menelusuri lagu saat ini dengan menyeret dan menjatuhkan SeekBar.



Sayangnya, itu SeekBarterlalu dekat dengan area gerakan untuk kembali ke layar awal, karena itu gerakan cepat beralih ke aplikasi sebelumnya (QuickSwitch) dimulai, yang memberikan ketidaknyamanan pengguna.

Hal yang sama dapat terjadi di setiap tepi layar tempat area gerakan berada. Ada banyak contoh umum yang dapat menyebabkan konflik, seperti: Laci navigasi ( DrawerLayout), komidi putar ( ViewPager ), slider ( SeekBar), geser ke dalam daftar.

Yang membawa kita pada pertanyaan "bagaimana kita bisa memperbaikinya?" Untuk memfasilitasi pertanyaan ini, kami telah membuat diagram alur yang menawarkan jawaban berdasarkan situasinya.


Anda dapat menemukan diagram alir versi PDF di sini .

Saya harap pertanyaannya tidak memerlukan penjelasan, tetapi untuk berjaga-jaga, saya akan membahasnya masing-masing:

1. Apakah aplikasi perlu menyembunyikan bilah navigasi dan status?


Pertanyaan pertama adalah apakah use case utama untuk aplikasi Anda mengharuskan menyembunyikan bilah navigasi dan / atau status. Dengan bersembunyi, maksud kami panel sistem ini tidak terlihat sama sekali. Ini tidak berarti bahwa Anda telah menerapkan konsep "ujung ke ujung" atau sesuatu yang serupa dalam aplikasi Anda.

Kemungkinan alasan untuk menjawab "ya" untuk pertanyaan ini:


Contoh umum aplikasi yang harus menjawab "ya" untuk pertanyaan ini adalah permainan, pemutar video, pemirsa foto, aplikasi menggambar.

2. Skenario utama untuk menggunakan UI melibatkan gesekan di / sekitar area gerakan?


Pertanyaan ini mengetahui apakah UI Anda mengandung elemen apa pun di / di sebelah area gerakan ("kembali" dan "rumah") yang harus digesek oleh pengguna.

Game biasanya mengatakan ya karena kenyataan itu

  • Kontrol pada layar biasanya terletak di dekat tepi kiri / kanan dan bagian bawah layar.
  • Di beberapa gim, Anda perlu menggesek elemen yang ada di layar.

Selain game, contoh umum UI yang seharusnya mengatakan ya adalah:

  • UI memotong foto di mana bingkai yang dapat diseret juga berada di dekat tepi kiri dan kanan layar.
  • Aplikasi menggambar tempat pengguna dapat menggambar di atas kanvas yang menutupi seluruh layar.

3. Tampilan yang sering digunakan di / sekitar area gerakan?


Saya harap ini pertanyaan yang cukup sederhana. Ini juga termasuk tampilan, yang meliputi area gerakan, dan kemudian meluas ke sebagian besar layar, misalnya, DrawerLayoutatau yang besar ViewPager.

4. View melibatkan swipe / drag?


Kami sedikit mengubah taktik dan mulai melihat pandangan individu. Untuk setiap pandangan yang Anda jawab dalam pertanyaan ketiga, kami membuat klarifikasi kecil: haruskah pengguna menggesek / menariknya?

Ada banyak contoh di mana Anda harus menjawab "yaยป: SeekBars, BottomSheet atau bahkan PopupMenu(Anda harus drag untuk terbuka).

5. Apakah tampilan sepenuhnya / umumnya terletak di bawah area gerakan?


Berdasarkan pertanyaan keempat, kami sekarang mengklarifikasi apakah pandangan sepenuhnya atau terutama terletak di area gerakan.

Jika tampilan Anda berada dalam wadah yang dapat digulir seperti ini RecyclerView, pikirkan pertanyaan ini sedikit berbeda: apakah tampilan yang diperluas sepenuhnya berada di bawah area gerakan di semua posisi gulir ? Jika pengguna dapat menggulir tampilan dari bawah area gerakan, maka Anda tidak perlu melakukan apa pun.

Dalam diagram di atas, Anda mungkin melihat layar penuh korsel ( ViewPager) sebagai contoh jawaban negatif dan bertanya-tanya mengapa kasus ini tidak perlu ditangani. Hal ini disebabkan oleh fakta bahwa area gerakan kiri / kanan lebarnya relatif kecil (default: 20dpmasing-masing) dibandingkan dengan lebar tampilan. Khaslebar layar ponsel Anda dalam orientasi potret adalah ~ 360dp, meninggalkan ~ 320dp ruang kosong di mana pengguna tidak mengalami kesulitan (ini hampir 90% dari layar). Bahkan dengan margin / indentasi internal, pengguna masih dapat dengan nyaman menggulung carousel.

6. Apakah batas tampilan tumpang tindih dengan area gerakan yang diperlukan?


Pertanyaan terakhir mengklarifikasi apakah pandangan berada di bawah area gerakan yang diperlukan. Jika Anda mengingat artikel kami sebelumnya , Anda akan ingat bahwa area wajib gerakan sistem adalah area layar di mana gerakan sistem selalu diutamakan.

Di Android 10, hanya ada satu area gerakan wajib, yang terletak di bagian bawah layar, yang memungkinkan pengguna untuk kembali ke rumah atau membuka aplikasi terbaru mereka. Ini mungkin berubah di rilis platform yang akan datang, tetapi sekarang kita hanya perlu bekerja dengan tampilan di bagian bawah layar.

Contoh umum adalah:

  • BottomSheet Modeless , karena mereka cenderung runtuh menjadi tampilan seret-dan-jatuhkan kecil di bagian bawah layar.
  • Korsel yang bergulir secara horizontal di bagian bawah layar, misalnya, antarmuka dengan stiker.

Sekarang setelah kami menyelesaikan pertanyaan, kami harap Anda dapat menemukan salah satu solusinya, jadi mari kita lihat masing-masing secara lebih rinci.

Tidak ada konflik yang harus ditangani


Mari kita mulai dengan "solusi" paling sederhana, tapi jangan lakukan apa-apa !

Tentu saja, mungkin masih ada ruang untuk optimisasi yang dapat Anda lakukan (lihat bagian di bawah), tetapi untungnya tidak ada masalah serius menggunakan aplikasi dengan mode navigasi gerakan diaktifkan.

Jika jadwal telah membawa Anda ke sini, tetapi Anda masih merasa ada masalah, beri tahu kami . Mungkin kita melewatkan sesuatu.

Tampilan bergerak dari area gerakan


Seperti yang kami pelajari dari artikel kami sebelumnya , insets ada untuk memberi tahu aplikasi Anda di mana zona isyarat sistem berada di layar. Salah satu metode yang dapat kita gunakan untuk menyelesaikan konflik isyarat adalah memindahkan segala pandangan yang bertentangan dari area isyarat. Ini sangat penting untuk tampilan di bagian bawah layar, karena area ini adalah zona gerakan wajib, dan aplikasi tidak dapat menggunakan API pengecualian gerakan di sana.

Mari kita lihat contoh lagi. Kami memiliki antarmuka pemutar musik yang kami tunjukkan di atas. Ini berisi SeekBar, terletak di bagian bawah layar, memungkinkan pengguna untuk menelusuri lagu.


Pemutar musik UI dengan SeekBar di bagian bawah layar

Tetapi ketika pengguna mencoba untuk melewatkan lagu, ini terjadi:


Merekam gerakan sistem yang bertentangan dengan SeekBar

Ini karena area bawah gerakan tumpang tindih dengan SeekBar, sehingga gerakan kembali mengambil prioritas. Berikut ini visualisasi dari zona gerakan:



Solusi sederhana


Solusi paling sederhana di sini adalah menambahkan indent / margin ekstra sehingga SeekBar bergerak naik dari area gerakan. Sesuatu seperti ini:



Jika kami menyeret SeekBar dalam contoh ini, Anda akan melihat bahwa kami tidak lagi mengaktifkan gestur homecoming:


SeekBar tidak lagi bertentangan dengan gestur sistem yang lebih rendah.

Untuk mengimplementasikan ini, kita perlu menggunakan inset gesture sistem baru yang tersedia di API 29 dan Jetpack Core library v1.2.0 (saat ini dalam alpha ). Pada contoh, kami meningkatkan indentasi bawah SeekBaragar sesuai dengan nilai inset gerakan rendah :

ViewCompat.setOnApplyWindowInsetsListener(seekBar) { view, insets ->
     //      view ,    system gesture insets
    view.updatePadding(
        bottom = insets.systemGestureInsets.bottom
    )
    insets
}

Jika Anda tertarik mempelajari cara membuatnya lebih mudah untuk dikerjakan WindowInsets, Anda dapat membaca artikel kami yang lain tentang topik ini:

WindowInsets - Layers pendengar

Tindakan selanjutnya


Pada titik ini, Anda dapat memutuskan bahwa pekerjaan sudah dilakukan, dan untuk beberapa tata letak ini mungkin merupakan solusi terakhir. Tetapi dalam contoh kami, antarmuka pengguna mundur secara visual dengan banyak ruang yang hilang di bawah SeekBar. Jadi, alih-alih hanya mendorong tampilan ke atas, kita dapat mendesain ulang tata letak untuk menghindari kehilangan ruang:


SeekBarpindah ke bagian atas panel pemutaran.

Di sini kami telah pindah SeekBarke bagian atas panel pemutaran, sepenuhnya di luar area gerakan. Ini berarti bahwa kita tidak perlu lagi menambah ketinggian panel secara artifisial untuk mengakomodasi SeekBar.

, . ยซ ยป.

API


Dalam artikel kami sebelumnya, kami menyebutkan bahwa "aplikasi memiliki kemampuan untuk mengecualikan gerakan sistem untuk bagian layar tertentu . " Aplikasi melakukan ini menggunakan API pengecualian gerakan, yang pertama kali muncul di Android 10.

Ada dua fungsi berbeda yang disediakan sistem untuk mengecualikan area gerakan: View.setSystemGestureExclusionRects()dan Window.setSystemGestureExclusionRects(). Apa yang harus Anda gunakan tergantung pada aplikasi: jika Anda menggunakan Android View, sistem lebih suka tampilan API, jika tidak gunakan WindowAPI.

Perbedaan utama antara kedua API adalah bahwa Window APImengharapkan persegi panjang berada di ruang koordinat jendela. Jika Anda menggunakan tampilan, Anda biasanya akan bekerja di ruang koordinat tampilan sebagai gantinya. Lihat API menangani transformasi antara ruang koordinat, yaitu, Anda hanya perlu memberi alasan dalam hal konten tampilan.

Mari kita lihat sebuah contoh. Kita akan menggunakan contoh pemutar musik kita lagi, yang SeekBarterletak di seluruh lebar layar. Kami memperbaiki konflik SeekBardengan gerakan untuk kembali ke layar beranda di bagian sebelumnya, tetapi kami masih memiliki area gerak kiri dan kanan yang perlu kami tangani.

Mari kita lihat apa yang terjadi ketika pengguna mencoba melewatkan lagu ketika "slider"SeekBar(drag melingkar) terletak di dekat salah satu tepi:


SeekBar memiliki konflik dengan area gerakan belakang

Karena slider berada di bawah area gerakan kanan, sistem percaya bahwa pengguna mencoba untuk kembali menggunakan gerakan, oleh karena itu, menunjukkan panah belakang. Ini merepotkan bagi pengguna, karena mereka mungkin tidak ingin kembali saat ini. Kami dapat memperbaiki ini menggunakan API pengecualian gerakan yang disebutkan di atas untuk mengecualikan batas slider.

API pengecualian gerakan biasanya dipanggil dari dua tempat: onDraw()saat tampilan Anda ditampilkan, dan onLayout()sebaliknya. Pandangan Anda berlaluList<Rect>berisi semua persegi panjang yang akan dikecualikan. Seperti disebutkan sebelumnya, persegi panjang ini harus dalam sistem koordinat pandangan mereka sendiri.

Biasanya Anda membuat fungsi seperti ini yang akan dipanggil dari onLayout()dan / atau onDraw():

private val gestureExclusionRects = mutableListOf<Rect>()
private fun updateGestureExclusion() {
   //   ,      Android 10+
   if (Build.VERSION.SDK_INT < 29) return
  // -,     
   gestureExclusionRects.clear()
      //   ,    .  SeekBar    .
   thumb?.also { t ->
       gestureExclusionRects += t.copyBounds()
   }
   //            view,       ,     
   // ,       
   systemGestureExclusionRects = gestureExclusionRects
}

Contoh lengkap dapat ditemukan di sini .

Setelah kami menambahkan ini, memutar di dekat tepi berfungsi seperti yang diharapkan:


SeekBar bekerja di area gerakan belakang

Catatan pada contoh di atas. SeekBarsudah melakukan ini secara otomatis untuk Anda di Android 10, jadi tidak perlu melakukannya sendiri. Di sini kami melakukannya hanya sebagai contoh untuk menunjukkan garis besar umum.

Keterbatasan


Meskipun API pengecualian gerakan mungkin tampak sebagai solusi sempurna untuk menyelesaikan semua konflik gerakan, ini sebenarnya bukan masalahnya. Menggunakan API pengecualian gerakan, Anda menyatakan bahwa gerakan aplikasi Anda lebih penting daripada tindakan pengembalian sistem. Ini adalah pernyataan yang kuat, jadi API ini dirancang untuk menjadi pintu darurat saat Anda tidak dapat melakukan apa pun.

Dengan menggunakan API pengecualian gerakan, Anda menyatakan bahwa gerakan aplikasi Anda lebih penting daripada tindakan sistem pelacakan mundur.

Karena perilaku yang disediakan oleh API dapat melanggar pengalaman pengguna yang nyaman, sistem membatasi penggunaannya: aplikasi hanya dapat mengecualikan hingga 200dp per edge.

Berikut adalah beberapa pertanyaan umum yang dimiliki pengembang ketika mereka mendengar ini:

Mengapa pembatasan itu perlu? Saya harap penjelasan di atas telah membawa Anda ke suatu alasan. Kami percaya bahwa sangat penting bagi pengguna untuk dapat secara konsisten kembali dari gesekan samping. Secara konsisten di seluruh perangkat, bukan satu aplikasi. Pembatasan ini mungkin tampak terlalu ketat, tetapi hanya satu aplikasi, tidak termasuk seluruh tepi layar, sudah cukup untuk menyebabkan ketidaknyamanan bagi pengguna, yang mengarah pada penghapusan aplikasi, atau ke sesuatu yang lebih radikal.

Dengan kata lain, sistem navigasi harus selalu konsisten dan mudah digunakan.

Mengapa 200dp?Argumen untuk 200dp cukup mudah. Seperti yang kami sebutkan sebelumnya, API pengecualian gerakan dimaksudkan untuk digunakan sebagai upaya terakhir, sehingga batas ini dihitung sebagai kelipatan dari beberapa target sentuh penting. Ukuran minimum yang disarankan untuk target sensorik adalah 48dp0,4 target sensorik ร— 48dp = 192dp. Tambahkan lebih banyak lekukan dan kami mendapatkan nilainya 200dp.

Bagaimana jika saya harus mengecualikan lebih dari 200dp per edge? Sistem akan mengecualikan hanya 200dp terendah yang Anda minta.


Sistem ini memungkinkan permintaan untuk ketinggian total 200 dp, dihitung dari tepi bawah

tampilan Saya di luar layar, apakah ini dianggap sebagai batas?Tidak, sistem hanya mempertimbangkan persegi panjang yang dikecualikan yang ada di dalam layar. Demikian pula, jika tampilan sebagian pada layar, hanya bagian yang terlihat dari persegi panjang yang diminta yang diperhitungkan.

Selami posting selanjutnya


Mungkin setelah membaca ini, Anda bertanya-tanya mengapa kami tidak mempertimbangkan sisi kanan diagram alur. Solusi di bawah ini dirancang khusus untuk aplikasi yang menggunakan seluruh layar dalam rendering. Kita akan membicarakannya di bagian selanjutnya.






All Articles