Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> Android

Thêm Custom View vào AlertDialog Android

AlertDialog với Custom View (Layout tùy chỉnh)

Sử dụng AlertDialog.Builder.setView(View) để hiển thị layout tùy chỉnh hoàn toàn trong dialog (form nhập liệu, layout phức tạp, v.v.).

Bước 1: Tạo dự án mới

Khởi tạo project Android Studio.

Bước 2: Layout chính (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">

    <TextView
        android:id="@+id/click"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Click to show custom dialog"
        android:textSize="24sp"
        android:padding="24dp" />

</LinearLayout>

Bước 3: Custom Dialog Layout (res/layout/custom.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="wrap_content"
    android:orientation="vertical"
    android:padding="24dp">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Nhập tên của bạn"
        android:textSize="18sp"
        android:textStyle="bold"
        android:layout_marginBottom="16dp" />

    <EditText
        android:id="@+id/editText"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="Tên..."
        android:inputType="textPersonName"
        android:padding="12dp"
        android:background="@android:drawable/editbox_background" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:layout_marginTop="16dp">
        
        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="Tuổi: "
            android:gravity="center_vertical"
            android:paddingEnd="8dp" />
            
        <EditText
            android:id="@+id/editAge"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:hint="Tuổi"
            android:inputType="number"
            android:padding="12dp" />
    </LinearLayout>

</LinearLayout>

Bước 4: MainActivity.java

package com.example.myapplication;

import android.annotation.TargetApi;
import android.content.DialogInterface;
import android.os.Build;
import android.os.Bundle;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {
    private TextView text;
    
    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        text = findViewById(R.id.click);
        text.setOnClickListener(v -> showAlertDialog());
    }
    
    private void showAlertDialog() {
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        
        // Inflate custom layout
        final View customLayout = getLayoutInflater().inflate(R.layout.custom, null);
        builder.setView(customLayout);
        
        // Nút xác nhận - lấy dữ liệu từ custom view
        builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                EditText editText = customLayout.findViewById(R.id.editText);
                EditText editAge = customLayout.findViewById(R.id.editAge);
                
                String name = editText.getText().toString().trim();
                String ageStr = editAge.getText().toString().trim();
                
                if (name.isEmpty()) {
                    Toast.makeText(MainActivity.this, "Vui lòng nhập tên", Toast.LENGTH_SHORT).show();
                    return;
                }
                
                String message = "Tên: " + name;
                if (!ageStr.isEmpty()) {
                    message += ", Tuổi: " + ageStr;
                }
                
                Toast.makeText(MainActivity.this, message, Toast.LENGTH_LONG).show();
            }
        });
        
        builder.setNegativeButton("Hủy", (dialog, which) -> dialog.dismiss());
        
        AlertDialog dialog = builder.create();
        dialog.setCanceledOnTouchOutside(false);
        dialog.show();
    }
}

Quan trọng: Truy xuất View từ Custom Layout

  • Phải giữ reference đến customLayout (final hoặc field)
  • Dùng customLayout.findViewById() - KHÔNG dùng findViewById() của Activity
  • Lấy dữ liệu trong callback setPositiveButton hoặc setNeutralButton

Custom Dialog hoàn toàn (Không dùng AlertDialog.Builder)

// Tùy chỉnh hoàn toàn: không title, không button mặc định, animation riêng
Dialog dialog = new Dialog(this, R.style.CustomDialogTheme);
dialog.setContentView(R.layout.custom_dialog_full);
dialog.setCancelable(true);
dialog.setCanceledOnTouchOutside(true);

// Tự xử lý button trong layout
Button btnOk = dialog.findViewById(R.id.btnOk);
Button btnCancel = dialog.findViewById(R.id.btnCancel);
btnOk.setOnClickListener(v -> { /* logic */ dialog.dismiss(); });
btnCancel.setOnClickListener(v -> dialog.dismiss());

dialog.show();

Style cho Custom Dialog (res/values/styles.xml)

<style name="CustomDialogTheme" parent="Theme.AppCompat.Light.Dialog">
    <item name="android:windowBackground">@android:color/transparent</item>
    <item name="android:windowNoTitle">true</item>
    <item name="android:windowIsFloating">true</item>
    <item name="android:windowMinWidthMajor">90%</item>
    <item name="android:windowMinWidthMinor">90%</item>
</style>

Bottom Sheet Dialog (Material Design)

// Cần dependency: implementation 'com.google.android.material:material:1.4.0+'
import com.google.android.material.bottomsheet.BottomSheetDialog;

BottomSheetDialog bottomSheetDialog = new BottomSheetDialog(this);
View bottomSheetView = getLayoutInflater().inflate(R.layout.bottom_sheet_layout, null);
bottomSheetDialog.setContentView(bottomSheetView);
bottomSheetDialog.show();

So sánh các loại Dialog

Lifecycle aware, rotation-safe, back stack

Loại API Ưu điểm Nhược điểm
AlertDialog + setView Builder.setView() Đơn giản, có sẵn button, title Giới hạn tùy chỉnh UI chrome
Dialog tùy chỉnh new Dialog() Hoàn toàn kiểm soát UI Phải tự xử lý mọi thứ
BottomSheetDialog Material Components Modern UX, swipe dismiss, drag handle Yêu cầu Material Components lib
DialogFragment FragmentManager Phức tạp hơn

Best Practices

  • Luôn dùng DialogFragment cho dialog phức tạp (xử lý rotation, lifecycle)
  • Validate input trước khi dismiss
  • Dùng TextInputLayout (Material) cho EditText trong dialog
  • Cân nhắc BottomSheetDialog cho UX hiện đại