Menyediakan navigasi Kembali yang tepat

Navigasi Kembali adalah cara pengguna bergerak mundur dalam histori layar-layar yang sebelumnya mereka kunjungi. Semua perangkat Android menyediakan tombol Kembali untuk navigasi semacam ini, karena itu aplikasi Anda tidak perlu menambahkan tombol Kembali ke UI.

Dalam hampir semua situasi, sistem akan mempertahankan back stack aktivitas selama pengguna menavigasi aplikasi Anda. Dengan cara ini, sistem dapat menavigasi mundur dengan tepat ketika pengguna menekan tombol Kembali. Namun, ada kalanya aplikasi Anda harus menentukan perilaku Kembali secara manual untuk memberikan pengalaman pengguna terbaik.

Lihat juga Mendesain Navigasi Kembali dan Naik, Tugas dan back stack, dan desain Android: navigasi.

Pola navigasi yang mengharuskan Anda menentukan perilaku Kembali secara manual meliputi:

Cara menerapkan navigasi Kembali dengan tepat dalam situasi ini dijelaskan dalam bagian di bawah.

Menyintesis Back Stack baru untuk Deep Link

Biasanya, sistem secara bertahap membuat back stack saat pengguna beralih dari satu aktivitas ke aktivitas berikutnya. Namun, saat pengguna memasuki aplikasi Anda dengan deep link yang memulai aktivitas dalam tugasnya sendiri, Anda perlu menyintesis back stack baru karena aktivitas tersebut berjalan dalam tugas baru tanpa back stack sama sekali.

Misalnya, saat notifikasi membawa pengguna ke aktivitas yang berada jauh di dalam hierarki aplikasi, Anda perlu menambahkan aktivitas ke dalam back stack tugas sehingga jika pengguna menekan tombol Kembali, mereka akan bergerak naik dalam hierarki aplikasi, bukannya keluar dari aplikasi Anda. Pola ini dijelaskan lebih lanjut dalam panduan desain Navigasi.

Menentukan aktivitas induk dalam manifes

Mulai Android 4.1 (API level 16), Anda dapat mendeklarasikan induk logis dari setiap aktivitas dengan menentukan atribut android:parentActivityName dalam elemen <activity>. Hal ini memungkinkan sistem untuk memfasilitasi pola navigasi karena sistem dapat menentukan lokasi navigasi Kembali atau Naik yang logis dengan informasi ini.

Jika aplikasi Anda mendukung Android 4.0 dan yang lebih lama, sertakan Library Dukungan dengan aplikasi Anda dan tambahkan elemen <meta-data> di dalam <activity>. Kemudian, tentukan aktivitas induk sebagai nilai untuk android.support.PARENT_ACTIVITY yang cocok dengan atribut android:parentActivityName.

Contoh:

<application ... >
    ...
    <!-- The main/home activity (it has no parent activity) -->
    <activity
        android:name="com.example.myfirstapp.MainActivity" ...>
        ...
    </activity>
    <!-- A child of the main activity -->
    <activity
        android:name="com.example.myfirstapp.DisplayMessageActivity"
        android:label="@string/title_activity_display_message"
        android:parentActivityName="com.example.myfirstapp.MainActivity" >
        <!-- The meta-data element is needed for versions lower than 4.1 -->
        <meta-data
            android:name="android.support.PARENT_ACTIVITY"
            android:value="com.example.myfirstapp.MainActivity" />
    </activity>
</application>

Dengan aktivitas induk yang dideklarasikan semacam ini, Anda dapat menggunakan NavUtils API untuk menyintesis back stack baru dengan mengidentifikasi aktivitas yang merupakan induk yang tepat untuk setiap aktivitas.

Membuat back stack saat memulai aktivitas

Penambahan aktivitas ke back stack dimulai setelah peristiwa yang membawa pengguna ke aplikasi Anda. Artinya, bukannya memanggil startActivity(), gunakan TaskStackBuilder API untuk menentukan setiap aktivitas yang harus ditempatkan di dalam back stack baru. Selanjutnya, mulai aktivitas target dengan memanggil startActivities(), atau buat PendingIntent yang sesuai dengan memanggil getPendingIntent().

Misalnya, saat notifikasi membawa pengguna ke aktivitas yang berada jauh di dalam hierarki aplikasi, Anda dapat menggunakan kode ini untuk membuat PendingIntent yang memulai aktivitas dan memasukkan back stack ke dalam tugas target:

Kotlin

val detailsIntent = Intent(this, DetailsActivity::class.java)

val pendingIntent: PendingIntent? = TaskStackBuilder.create(this)
        // add all of DetailsActivity's parents to the stack,
        // followed by DetailsActivity itself
        .addNextIntentWithParentStack(detailsIntent)
        .getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT)

val builder = NotificationCompat.Builder(this)
        .setContentIntent(pendingIntent)
...

Java

// Intent for the activity to open when user selects the notification
Intent detailsIntent = new Intent(this, DetailsActivity.class);

// Use TaskStackBuilder to build the back stack and get the PendingIntent
PendingIntent pendingIntent =
        TaskStackBuilder.create(this)
                        // add all of DetailsActivity's parents to the stack,
                        // followed by DetailsActivity itself
                        .addNextIntentWithParentStack(detailsIntent)
                        .getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);

NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
builder.setContentIntent(pendingIntent);
...

PendingIntent yang dihasilkan menetapkan tidak hanya aktivitas yang akan dimulai (seperti yang ditentukan oleh detailsIntent), tetapi juga back stack yang harus dimasukkan ke dalam tugas tersebut (semua induk dari DetailsActivity yang ditentukan oleh detailsIntent). Sehingga saat DetailsActivity dimulai, menekan Kembali akan menavigasi mundur melalui setiap aktivitas induk dalam class DetailsActivity.

Catatan: Agar metode addNextIntentWithParentStack() berfungsi, Anda harus mendeklarasikan induk logis dari setiap aktivitas dalam file manifes, menggunakan atribut android:parentActivityName (dan elemen <meta-data> yang sesuai) seperti dijelaskan di atas.

Menerapkan Navigasi Mundur untuk Fragmen

Jika aplikasi Anda menggunakan fragmen, setiap objek FragmentTransaction dapat mewakili perubahan konteks yang harus ditambahkan ke back stack. Misalnya, jika menerapkan alur master/detail pada handset dengan cara menukar fragmen, Anda perlu memastikan bahwa menekan tombol Kembali pada layar detail akan mengembalikan pengguna ke layar master. Untuk melakukannya, panggil addToBackStack() sebelum meng-commit transaksi:

Kotlin

// Works with either the framework FragmentManager or the
// support package FragmentManager (supportFragmentManager).
supportFragmentManager.beginTransaction()
        .add(detailFragment, "detail")
        // Add this transaction to the back stack
        .addToBackStack(null)
        .commit()

Java

// Works with either the framework FragmentManager or the
// support package FragmentManager (getSupportFragmentManager).
getSupportFragmentManager().beginTransaction()
                           .add(detailFragment, "detail")
                           // Add this transaction to the back stack
                           .addToBackStack(null)
                           .commit();

Jika objek FragmentTransaction ada di back stack dan pengguna menekan tombol Kembali, FragmentManager akan menonaktifkan transaksi terbaru dari back stack dan melakukan tindakan sebaliknya (seperti menghapus fragmen jika transaksi menambahkannya).

Catatan: Anda tidak boleh menambahkan transaksi ke back stack jika transaksi tersebut untuk navigasi horizontal (seperti saat berpindah tab) atau ketika memodifikasi tampilan konten (seperti saat menyesuaikan filter). Untuk informasi lebih lanjut tentang kapan navigasi Kembali dapat digunakan, buka panduan desain Navigasi.

Jika aplikasi Anda memperbarui elemen antarmuka pengguna lain untuk menunjukkan status fragmen Anda saat ini, seperti bar tindakan, ingatlah untuk memperbarui UI saat Anda meng-commit transaksi. Anda harus memperbarui antarmuka pengguna setelah back stack berubah, selain saat meng-commit transaksi. Anda dapat mendeteksi kapan FragmentTransaction dikembalikan dengan menyiapkan FragmentManager.OnBackStackChangedListener:

Kotlin

supportFragmentManager.addOnBackStackChangedListener {
    // Update your UI here.
}

Java

getSupportFragmentManager().addOnBackStackChangedListener(
        new FragmentManager.OnBackStackChangedListener() {
            public void onBackStackChanged() {
                // Update your UI here.
            }
        });

Menerapkan Navigasi Kembali untuk WebView

Jika ada bagian dari aplikasi Anda yang dimuat di WebView, mungkin ada baiknya jika navigasi Kembali menyusuri seluruh histori browser. Untuk melakukannya, Anda dapat mengganti onBackPressed() dan proxy ke WebView jika terdapat status histori:

Kotlin

override fun onBackPressed() {
    if (mWebView.canGoBack()) {
        mWebView.goBack()
    } else {
        // Otherwise defer to system default behavior.
        super.onBackPressed()
    }
}

Java

@Override
public void onBackPressed() {
    if (mWebView.canGoBack()) {
        mWebView.goBack();
        return;
    }

    // Otherwise defer to system default behavior.
    super.onBackPressed();
}

Berhati-hatilah saat menggunakan mekanisme ini pada halaman yang sangat dinamis, yang dapat menghasilkan histori yang besar. Halaman yang menghasilkan histori ekstensif, misalnya halaman yang sering mengubah hash dokumen, dapat membuat pengguna bosan untuk menyelesaikan aktivitas.

Untuk informasi cara menggunakan WebView lebih lanjut, baca Membuat Aplikasi Web di WebView.