Hướng dẫn này trình bày cách ngăn chặn AlertDialog tự động đóng khi người dùng nhấn nút (Positive/Negative/Neutral). Mặc định, Dialog sẽ dismiss ngay khi bất kỳ nút nào được nhấn. Để kiểm soát hành vi này (ví dụ: validate input trước khi đóng), cần gán OnClickListener trực tiếp cho Button của Dialog sau khi show().
Các bước thực hiện
Bước 1: Tạo dự án mới
Mở Android Studio, chọn File → New Project và điền thông tin cần thiết.
Bước 2: Layout (res/layout/activity_main.xml)
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="https://schemas.android.com/apk/res/android"
xmlns:tools="https://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
</RelativeLayout>
Bước 3: Code MainActivity (src/MainActivity.java)
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Tạo và hiển thị dialog
final AlertDialog dialog = new AlertDialog.Builder(this)
.setTitle("Dialog của tôi")
.setMessage("Ví dụ thông điệp")
.setPositiveButton("OK", null) // Listener null - sẽ gán sau
.setNegativeButton("Hủy", null)
.show(); // QUAN TRỌNG: Phải show() trước khi getButton()
// Lấy button Positive sau khi show()
Button positiveButton = dialog.getButton(AlertDialog.BUTTON_POSITIVE);
positiveButton.setOnClickListener(v -> {
// Logic validate hoặc xử lý tại đây
Toast.makeText(MainActivity.this, "Không đóng dialog - xử lý tùy chỉnh", Toast.LENGTH_SHORT).show();
// Nếu muốn đóng thủ công:
// dialog.dismiss();
});
// Tương tự cho nút Negative nếu cần
Button negativeButton = dialog.getButton(AlertDialog.BUTTON_NEGATIVE);
negativeButton.setOnClickListener(v -> {
Toast.makeText(MainActivity.this, "Nhấn Hủy", Toast.LENGTH_SHORT).show();
dialog.dismiss(); // Đóng dialog khi nhấn Hủy
});
}
}
Bước 4: Cấu hình AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="https://schemas.android.com/apk/res/android"
package="app.com.sample">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Chạy ứng dụng
Kết nối thiết bị, nhấn Run. Dialog hiện ra ngay khi Activity khởi tạo. Nhấn "OK" - dialog KHÔNG đóng, hiện Toast. Nhấn "Hủy" - dialog đóng.

Giải thích cơ chế
- Tạo
AlertDialog.Buildervới listenernullcho các nút - Gọi
show()để dialog hiển thị và tạo các Button nội bộ - Dùng
dialog.getButton(AlertDialog.BUTTON_POSITIVE/NEGATIVE/NEUTRAL)để lấy tham chiếu Button thực tế - Gán
OnClickListenermới - ghi đè hành vi mặc định (dismiss) - Trong listener tùy chỉnh, tự quyết định có gọi
dialog.dismiss()hay không
Các trường hợp sử dụng phổ biến
- Validate form: Kiểm tra EditText trong dialog, chỉ đóng nếu hợp lệ
- Xác nhận hành động nguy hiểm: Yêu cầu nhập từ khóa, xác thực vân tay...
- Loading trong dialog: Nhấn nút → hiện progress → tải xong mới dismiss
- Multi-step dialog: Chuyển nội dung dialog thay vì đóng/mở mới
Cách hiện đại: MaterialAlertDialogBuilder (Material Components)
// Dependency: implementation 'com.google.android.material:material:1.9.0'
new MaterialAlertDialogBuilder(this)
.setTitle("Tiêu đề")
.setMessage("Nội dung")
.setPositiveButton("OK", (dialog, which) -> {
// Mặc định vẫn dismiss. Để không dismiss:
// Không thể dễ dàng override như AlertDialog cũ.
// Cách khuyên dùng: dùng View custom layout với Button tự quản lý
})
.show();
Best Practice: Custom Layout Dialog
Để kiểm soát hoàn toàn, tạo layout XML riêng và set cho dialog:
View dialogView = LayoutInflater.from(this).inflate(R.layout.dialog_custom, null);
EditText etInput = dialogView.findViewById(R.id.etInput);
Button btnOk = dialogView.findViewById(R.id.btnOk);
AlertDialog dialog = new AlertDialog.Builder(this)
.setView(dialogView)
.create(); // Không show() ngay
btnOk.setOnClickListener(v -> {
String text = etInput.getText().toString();
if (text.isEmpty()) {
etInput.setError("Không được để trống");
return; // Không dismiss
}
dialog.dismiss(); // Chỉ dismiss khi valid
});
dialog.show();
Cách này linh hoạt nhất, không phụ thuộc vào hành vi mặc định của AlertDialog buttons.