自定義 Dialog 嵌入 ListView 後,點擊 Item 無法直接調用 dialog.dismiss(),因為在 Adapter 的 getView() 或點擊監聽中無法直接訪問外部 Dialog 實例。
最簡單有效的方法是讓 Adapter 持有 Dialog 的弱引用,或在創建 Dialog 後將其傳給 Adapter:
public class MyAdapter extends BaseAdapter {
private final WeakReference<Dialog> dialogRef;
private final List<String> data;
public MyAdapter(Dialog dialog, List<String> data) {
this.dialogRef = new WeakReference<>(dialog);
this.data = data;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// ... 正常填充視圖
View view = ...;
view.setOnClickListener(v -> {
Dialog dialog = dialogRef.get();
if (dialog != null && dialog.isShowing()) {
dialog.dismiss();
}
});
return view;
}
}
// 使用時
Dialog dialog = new Dialog(context);
ListView listView = dialog.findViewById(R.id.list_view);
listView.setAdapter(new MyAdapter(dialog, dataList));
dialog.show();
若僅需簡單列表選擇,無需自定義布局,直接用 AlertDialog.Builder.setSingleChoiceItems() 或 setAdapter() 並設置 OnClickListener,點擊會自動關閉:
new AlertDialog.Builder(context)
.setTitle("選擇項目")
.setSingleChoiceItems(items, -1, (dialog, which) -> {
// 處理選中邏輯
dialog.dismiss(); // 自動關閉
})
.show();
Google 建議使用 DialogFragment 管理對話框生命週期,配合 RecyclerView 替代 ListView:
public class SelectDialogFragment extends DialogFragment {
@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
RecyclerView rv = new RecyclerView(requireContext());
rv.setLayoutManager(new LinearLayoutManager(requireContext()));
rv.setAdapter(new SelectAdapter(item -> dismiss()));
return new AlertDialog.Builder(requireContext())
.setView(rv)
.create();
}
}
WeakReference。dismiss() 前請判斷 dialog != null && dialog.isShowing()。android:focusable="false" 和 android:focusableInTouchMode="false",避免焦點攔截點擊事件。