Giới thiệu
Bài viết hướng dẫn cách xử lý hành động khi người dùng click vào nút Up (mũi tên back) trên Action Bar. Khác với việc chỉ bật hiển thị, bài này tập trung vào logic xử lý navigation.
Các bước thực hiện
Bước 1: Tạo project mới
Android Studio → File → New Project → Empty Activity.
Bước 2: Giao diện (res/layout/activity_main.xml)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center"
android:padding="16dp">
<TextView
android:id="@+id/tvStatus"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Up button action enabled"
android:textSize="18sp" />
</LinearLayout>
Bước 3: Code xử lý (MainActivity.kt)
package com.example.upbuttonaction
import android.os.Bundle
import android.view.MenuItem
import androidx.appcompat.app.AppCompatActivity
import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
supportActionBar?.title = "Detail Screen"
supportActionBar?.subtitle = "Tap Up to go back"
// Bật Up button
supportActionBar?.setDisplayHomeAsUpEnabled(true)
supportActionBar?.setDisplayShowHomeEnabled(true)
tvStatus.text = "Click nút mũi tên (Up) để quay lại"
}
// Cách 1: onSupportNavigateUp() - Khuyên dùng (Activity 1.0+)
override fun onSupportNavigateUp(): Boolean {
// Logic tùy chỉnh trước khi back
// saveData(), confirmDialog(), etc.
onBackPressedDispatcher.onBackPressed()
return true // Đã xử lý
}
// Cách 2: onOptionsItemSelected() - Cách cũ, vẫn hoạt động
override fun onOptionsItemSelected(item: MenuItem): Boolean {
return when (item.itemId) {
android.R.id.home -> {
// Xử lý click Home/Up
onBackPressedDispatcher.onBackPressed()
true
}
else -> super.onOptionsItemSelected(item)
}
}
}
So sánh 2 cách
| Phương thức | Ưu điểm | Nhược điểm |
|---|---|---|
onSupportNavigateUp() |
Semantic rõ ràng, tích hợp OnBackPressedDispatcher, hỗ trợ Navigation Component | Yêu cầu AppCompatActivity |
onOptionsItemSelected() |
Tương thích cũ, xử lý chung cho tất cả menu item | Phải check itemId thủ công, không semantic |
Xử lý nâng cao: Confirm dialog trước khi back
override fun onSupportNavigateUp(): Boolean {
if (hasUnsavedChanges) {
showConfirmDialog { onBackPressedDispatcher.onBackPressed() }
return true
}
return super.onSupportNavigateUp() // Default behavior (navigate up)
}
private fun showConfirmDialog(onConfirm: () -> Unit) {
AlertDialog.Builder(this)
.setTitle("Chưa lưu thay đổi")
.setMessage("Bạn có chắc chắn muốn thoát?")
.setPositiveButton("Thoát") { _, _ -> onConfirm() }
.setNegativeButton("Ở lại", null)
.show()
}
Tích hợp Navigation Component (Khuyên dùng cho app mới)
// Activity
val navController = findNavController(R.id.nav_host_fragment)
NavigationUI.setupActionBarWithNavController(this, navController)
// Fragment (nếu cần override)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Disable default Up handling để tự handle
requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner) {
if (navController.currentDestination?.id == R.id.detailFragment) {
// Custom logic
} else {
navController.navigateUp()
}
}
}
Lưu ý
- Luôn trả về
truenếu đã handle,falsehoặcsuperđể delegate. - Up button khác với Back button hệ thống (gesture/back button), nhưng hành động thường giống nhau.
- Trên Android 13+, Back predictive gesture có thể trigger trước Up button.