Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Android

วิธีป้องกันไม่ให้ Dialog ปิดเมื่อกดปุ่มใน Android

ภาพรวม

ตัวอย่างนี้สาธิตวิธีป้องกันไม่ให้ AlertDialog ปิดอัตโนมัติเมื่อกดปุ่ม Positive/Negative โดยการ Override OnClickListener หลังจาก show()

ขั้นตอนที่ 1: สร้างโปรเจกต์ใหม่

เปิด Android Studio → File → New Project และกรอกข้อมูลที่จำเป็น

ขั้นตอนที่ 2: เลย์เอาต์ (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>

ขั้นตอนที่ 3: โค้ดหลัก (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);

        // สร้างและแสดง Dialog ทันที
        final AlertDialog dialog = new AlertDialog.Builder(this)
            .setTitle("My Alert Dialog")
            .setMessage("Example Message")
            .setPositiveButton("Ok", null) // null = ไม่ปิดอัตโนมัติ
            .setNegativeButton("Cancel", null)
            .show();

        // Override ปุ่ม Positive หลังจาก show()
        Button positiveButton = dialog.getButton(AlertDialog.BUTTON_POSITIVE);
        positiveButton.setOnClickListener(v -> {
            // ตรวจสอบเงื่อนไขก่อนปิด
            boolean isValid = true; // ตัวอย่าง validation
            
            if (isValid) {
                Toast.makeText(MainActivity.this, "Validation passed, closing...", Toast.LENGTH_SHORT).show();
                dialog.dismiss(); // ปิดเอง
            } else {
                Toast.makeText(MainActivity.this, "Do not dismiss - Invalid input", Toast.LENGTH_SHORT).show();
                // ไม่เรียก dismiss() -> Dialog ยังคงเปิดอยู่
            }
        });

        // ปุ่ม Negative ปิดปกติ
        Button negativeButton = dialog.getButton(AlertDialog.BUTTON_NEGATIVE);
        negativeButton.setOnClickListener(v -> dialog.dismiss());
    }
}

ขั้นตอนที่ 4: 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>

การทดสอบ

รันแอป จะแสดง Dialog ทันที กด OK จะแสดง Toast "Do not dismiss" และ Dialog ไม่ปิด กด Cancel จะปิดได้ปกติ

วิธีป้องกันไม่ให้ Dialog ปิดเมื่อกดปุ่มใน Android

วิธีอื่นๆ และ Best Practices

1. ใช้ DialogFragment (แนะนำ)

public class CustomDialogFragment extends DialogFragment {
    @NonNull
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
        View view = LayoutInflater.from(getActivity()).inflate(R.layout.dialog_custom, null);
        
        builder.setView(view);
        
        AlertDialog dialog = builder.create();
        
        // ตั้งค่าหลัง create
        dialog.setOnShowListener(d -> {
            Button btn = dialog.getButton(AlertDialog.BUTTON_POSITIVE);
            btn.setOnClickListener(v -> {
                if (validateInput()) {
                    dialog.dismiss();
                }
            });
        });
        
        return dialog;
    }
}

2. ใช้ MaterialAlertDialogBuilder (Material Components)

new MaterialAlertDialogBuilder(this)
    .setTitle("Title")
    .setMessage("Message")
    .setPositiveButton("OK", (dialog, which) -> {
        // dialog จะปิดอัตโนมัติ
    })
    .setNegativeButton("Cancel", null)
    .show();

3. สร้าง Custom Dialog Class

public class ValidatedDialog extends AlertDialog {
    public ValidatedDialog(@NonNull Context context) {
        super(context);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.dialog_validated);
        
        Button btnOk = findViewById(R.id.btnOk);
        btnOk.setOnClickListener(v -> {
            if (validate()) {
                dismiss();
            }
        });
    }
    
    private boolean validate() { /* ... */ return true; }
}

สรุปเทคนิค

วิธีข้อดีข้อเสีย
setOnClickListener หลัง show()ง่าย ใช้กับ AlertDialog ได้เลยต้องทำหลัง show() เท่านั้น
DialogFragmentLifecycle-safe, Configuration change safeซับซ้อนกว่า
Custom Dialog ClassReusable, Testableโค้ดเยอะกว่า
⚠️ ข้อควรระวัง: ต้องตั้ง OnClickListener หลัง เรียก show() เท่านั้น เพราะปุ่มยังไม่สร้างก่อน show()