Bersiaplah untuk menggunakan 12L, yaitu update fitur baru untuk perangkat layar besar yang akan hadir awal tahun depan. Coba sekarang juga!

Efek overscroll

Pada perangkat yang menjalankan Android 12 dan yang lebih tinggi, perilaku visual untuk peristiwa overscroll berubah.

Pada Android 11 dan yang lebih rendah, peristiwa overscroll menyebabkan elemen visual memiliki glow; sementara di Android 12 dan yang lebih tinggi, elemen visual meregang dan memantul kembali pada peristiwa tarik, lalu mengayun dan memantul kembali saat peristiwa ayun:

Perilaku overscroll baru memengaruhi animasi penarikan dan pengayunan.

Perilaku ini berlaku untuk semua aplikasi yang menggunakan EdgeEffect, dan untuk semua konten yang ada di dalam class berikut:

Efek visual berfungsi untuk scroll vertikal dan horizontal. Karena diterapkan secara default untuk semua aplikasi yang tidak menggunakan overscroll, makan fitur ini akan memberikan pengalaman UI yang lebih konsisten bagi pengguna.

Praktik terbaik

Untuk memastikan pengalaman overscroll baru berfungsi baik dengan aplikasi Anda, ikuti praktik terbaik berikut:

Meregangkan penggunaan EdgeEffect

EdgeEffect menambahkan dua API untuk menerapkan efek overscroll regangan.

float getDistance()
float onPullDistance(float deltaDistance, float displacement)

Untuk memberikan pengalaman terbaik menggunakan overscroll regangan kepada pengguna, lakukan hal berikut:

  • Saat pengguna melepas dan menyentuh konten selama animasi rilis, daftarkan sentuhan sebagai "tonton". Pengguna menghentikan animasi dan mulai memanipulasi regangan lagi.
  • Saat pengguna menggerakkan jari ke arah yang berlawanan dari regangan, lepaskan regangan hingga benar-benar hilang lalu mulailah men-scroll.
  • Jika pengguna mengayuh saat meregangkan, ayunkan EdgeEffect untuk meningkatkan efek regangan.

Menonton animasi

Saat pengguna menonton animasi regangan aktif, EdgeEffect.isFinished() akan menampilkan false. Hal ini menunjukkan bahwa regangan harus dimanipulasi oleh gerakan sentuh. Di sebagian besar container, hal ini terdeteksi di onInterceptTouchEvent(), seperti yang ditunjukkan dalam cuplikan kode berikut:

Kotlin

override fun onInterceptTouchEvent(ev: MotionEvent): Boolean {
  ...
  when (action and MotionEvent.ACTION_MASK) {
    MotionEvent.ACTION_DOWN ->
      ...
      isBeingDragged = !edgeEffectBottom.isFinished() ||
          !edgeEffectTop.isFinished()
      ...
  }
  return isBeingDragged
}

Java

@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
  ...
  switch (action & MotionEvent.ACTION_MASK) {
    case MotionEvent.ACTION_DOWN:
      ...
      mIsBeingDragged = !mEdgeEffectBottom.isFinished()
          || !mEdgeEffectTop.isFinished();
      ...

Pada contoh sebelumnya, onInterceptTouchEvent() menampilkan true jika mIsBeingDragged adalah true sehingga akan cukup untuk menggunakan peristiwa sebelum turunan memiliki peluang untuk memakainya.

Merilis efek overscroll

Efek regangan harus dilepaskan sebelum men-scroll agar regangan tidak diterapkan ke konten scroll. Contoh kode berikut menunjukkan hal ini:

Kotlin

override fun onTouchEvent(ev: MotionEvent): Boolean {
  val activePointerIndex = ev.actionIndex

  when (ev.getActionMasked()) {
    MotionEvent.ACTION_MOVE ->
      val x = ev.getX(activePointerIndex)
      val y = ev.getY(activePointerIndex)
      var deltaY = y - mLastMotionY
      val pullDistance = deltaY / height
      val displacement = x / width

      if (deltaY < 0f && mEdgeEffectTop.distance > 0f) {
        deltaY -= height * mEdgeEffectTop
            .onPullDistance(pullDistance, displacement);
      }
      if (deltaY > 0f && mEdgeEffectBottom.distance > 0f) {
        deltaY += height * mEdgeEffectBottom
            .onPullDistance(-pullDistance, 1 - displacement);
      }

      ...
  }

Java

@Override
public boolean onTouchEvent(MotionEvent ev) {

  final int actionMasked = ev.getActionMasked();

  switch (actionMasked) {
    case MotionEvent.ACTION_MOVE:
      final float x = ev.getX(activePointerIndex);
      final float y = ev.getY(activePointerIndex);
      float deltaY = y - mLastMotionY;
      float pullDistance = deltaY / getHeight();
      float displacement = x / getWidth();

      if (deltaY < 0 && mEdgeEffectTop.getDistance() > 0) {
        deltaY -= getHeight() * mEdgeEffectTop
            .onPullDistance(pullDistance, displacement);
      }
      if (deltaY > 0 && mEdgeEffectBottom.getDistance() > 0) {
        deltaY += getHeight() * mEdgeEffectBottom
            .onPullDistance(-pullDistance, 1 - displacement);
      }
            ...

Saat menarik, sebelum meneruskan peristiwa sentuh ke scroll bertingkat atau menarik scroll, jarak tarik EdgeEffect harus digunakan. Dalam contoh kode sebelumnya, getDistance() menampilkan nilai positif saat efek tepi ditampilkan dan dapat dilepaskan dengan gerakan. Saat melepaskan regangan, peristiwa sentuh pertama kali digunakan oleh EdgeEffect sehingga akan benar-benar dilepaskan sebelum efek lainnya, seperti scroll bertingkat, ditampilkan. Anda dapat menggunakan getDistance() untuk mempelajari berapa jarak tarik yang diperlukan untuk melepaskan efek saat ini.

onPullDistance() berbeda dengan onPull() karena menampilkan jumlah penggunaan delta yang diteruskan. onPull() sebelumnya telah mengizinkan nilai negatif untuk total jarak efek glow. Pada Android 12 dan yang lebih tinggi, jika onPull() atau onPullDistance() diteruskan nilai deltaDistance negatif saat getDistance() adalah 0, tidak akan ada perubahan dalam regangan.

Memilih tidak ikut

Anda dapat memilih untuk tidak melakukan overscroll dalam file tata letak XML atau secara terprogram. Kode XML berikut menampilkan android:overScrollMode yang ditetapkan dalam file tata letak.

<!-- Via markup -->
<ScrollView
  ...
  android:overScrollMode="never"
  ...
>

Memilih tidak ikut secara terprogram seperti dalam cuplikan kode berikut:

Kotlin

<!-- Programmatically-->
...
recyclerview.overScrollMode = View.OVER_SCROLL_NEVER
...

Java

<!-- Programmatically-->
...
recyclerview.setOverScrollMode(View.OVER_SCROLL_NEVER);
...

Memberikan masukan

Masukan Anda sangat berarti bagi kami. Beri tahu kami jika Anda menemukan masalah atau memiliki ide untuk meningkatkan fitur ini. Lihat masalah yang ada sebelum membuat masalah baru. Anda dapat memberikan suara pada masalah yang ada dengan mengklik tombol bintang.

Melaporkan masalah baru

Lihat dokumentasi Issue Tracker untuk mengetahui informasi selengkapnya.