iT邦幫忙

2025 iThome 鐵人賽

DAY 19
0

Dialog

根據官網的解說,對話方塊是一個小型視窗,可提示使用者做出決定或輸入其他資訊。對話方塊不佔滿整個畫面,通常用於提示使用者必須回應才能繼續操作

而Dialog 類別是對話方塊的基礎類別,底下又有多種子類別

Ps.其實原先還有一個子類別叫做ProgressDialog,是 Android 中用來顯示載入中畫面的元件,但在API 26之後已被標記為Deprecated(不建議使用),如需要顯示進度條的對話框歡迎參考之前寫的ProgressBar解說


AlertDialog

最基礎的對話方塊,會顯示標題、內文和按鈕(最多三個),也可選取項目清單或自訂版面配置。

首先要先建立一個AlertDialog

AlertDialog.Builder dialog = new AlertDialog.Builder(MainActivity.this);

然後我們就可以開始進行版面配置,例如設置一個小icon

dialog.setIcon(android.R.drawable.ic_dialog_info);//設置圖示(系統預設)
dialog.setIcon(R.drawable.my_icon);//設置圖示(自訂)

設置標題跟內文

dialog.setTitle("標題");
dialog.setMessage("內文");

設置按鈕和點擊事件。注意:兩個按鈕時,左側按鈕用 setNegativeButton

//設置左邊按鈕(NegativeButton)和點擊事件
dialog.setNegativeButton("關閉", new DialogInterface.OnClickListener() {
    @Override
    public void onClick(DialogInterface dialogInterface, int i) {
        // TODO: ...
    }
});

//設置右邊按鈕(PositiveButton)和點擊事件
dialog.setPositiveButton("確定", new DialogInterface.OnClickListener() {
    @Override
    public void onClick(DialogInterface dialogInterface, int i) {
        // TODO: ...
    }
});

如果想設置3顆按鈕的AlertDialog,在設置按鈕時會跟兩顆按鈕時有所不同

AlertDialog.Builder dialog = new AlertDialog.Builder(MainActivity.this);
dialog.setTitle("普通對話框(3顆按鈕)");
dialog.setMessage("這是內文");
dialog.setIcon(android.R.drawable.ic_dialog_info);

//設置左邊按鈕和點擊事件,按鈕為3時左邊用NeutralButton
dialog.setNeutralButton("關閉", new DialogInterface.OnClickListener() {
    @Override
    public void onClick(DialogInterface dialogInterface, int i) {
        //TODO: ...
    }
});

//設置中間按鈕和點擊事件,按鈕為3時中間按鈕用NegativeButton
dialog.setNegativeButton("按鈕2", new DialogInterface.OnClickListener() {
    @Override
    public void onClick(DialogInterface dialogInterface, int i) {
        //TODO: ...
    }
});

dialog.setPositiveButton("按鈕3", new DialogInterface.OnClickListener() {
    @Override
    public void onClick(DialogInterface dialogInterface, int i) {
        //TODO: ...
    }
});

寫完記得加上dialog.show()才能顯示Dialog


除了按鈕以外,AlertDialog也可用來選取項目清單,分為直接點選、可變更選項和多選三種

無法更改選擇:

//列表內容
String[] items = {"Item1", "Item2", "Item3", "Item4"};
AlertDialog.Builder dialog = new AlertDialog.Builder(MainActivity.this);
dialog.setTitle("列表對話框Dialog");

// 設置item點擊事件處理
dialog.setItems(items, new DialogInterface.OnClickListener() {
    @Override
    public void onClick(DialogInterface dialogInterface, int i) {
        Toast.makeText(MainActivity.this, "你點擊了" + items[i], Toast.LENGTH_SHORT).show();
    }
});
dialog.show(); // 顯示dialog

可更改選擇:

choice = 1; //預設選擇Item2(從0開始)
String[] items = {"Item1", "Item2", "Item3", "Item4"};
AlertDialog.Builder dialog = new AlertDialog.Builder(MainActivity.this);

// 參數1:設置選項List;  參數2:設置預設選中項
dialog.setSingleChoiceItems(items, choice, new DialogInterface.OnClickListener() {
    @Override
    public void onClick(DialogInterface dialogInterface, int i) {
        choice = i;//紀錄使用者點選的選項之索引值
    }
});

dialog.setPositiveButton("單選對話框", new DialogInterface.OnClickListener() {
    @Override
    public void onClick(DialogInterface dialogInterface, int i) {
        Toast.makeText(MainActivity.this, "你選了" + items[choice], Toast.LENGTH_SHORT).show();
    }
});
dialog.show(); // 顯示dialog

多選:

String[] items = {"Item1", "Item2", "Item3", "Item4"};
// 設置默認選中項, false表示未選中, true反之
boolean choiceSets[] = {false, true, false, false};
AlertDialog.Builder dialog = new AlertDialog.Builder(MainActivity.this);
dialog.setTitle("多選對話框");

dialog.setMultiChoiceItems(items, choiceSets,
        new DialogInterface.OnMultiChoiceClickListener() {
            @Override
            public void onClick(DialogInterface dialogInterface, int i, boolean b) {
                choiceSets[i] = b;//紀錄使用者點選的選項之索引值,加入陣列
            }
        }
);

dialog.setPositiveButton("確定", new DialogInterface.OnClickListener() {
    @Override
    public void onClick(DialogInterface dialogInterface, int i) {
        String result = "";

        //把陣列裡的索引值一個一個抓出來顯示
        for (int k = 0; k < items.length; k++) {
            if (choiceSets[k]) {
                result += items[k] + "\\";
            }
        }
        Toast.makeText(MainActivity.this, "你選中了" + result, Toast.LENGTH_SHORT).show();
    }
});
dialog.show(); // 顯示dialog

建立自訂版面配置

如果你不喜歡預設的這些對話方塊,也可以使用自訂的版面配置,根據預設,自訂版面配置會填滿對話方塊視窗,但你可以用AlertDialog.Builder來新增按鈕和標題,請記住,若是想自訂版面配置,必須新建一個專門的xml檔,並在xml檔中將其設為顯示為對話方塊,如下

<activity android:theme="@android:style/Theme.Holo.Dialog" >

範例程式碼:

AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());

// 取得 LayoutInflater 物件
//將 XML 版面檔 (R.layout.dialog_signin) 轉換成View
LayoutInflater inflater = requireActivity().getLayoutInflater();

// 設置自訂的對話框版面
builder.setView(inflater.inflate(R.layout.dialog_signin, null))

// 設置按鈕與點擊事件
      builder.setPositiveButton(R.string.signin, new DialogInterface.OnClickListener() {
           @Override
           public void onClick(DialogInterface dialog, int id) {
               // 使用者點擊「登入」後的處理
           }
       })
       .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
           public void onClick(DialogInterface dialog, int id) {
               // 使用者點擊「取消」時,關閉對話框
               LoginDialogFragment.this.getDialog().cancel();
           }
       });

// 回傳建立好的 AlertDialog 實體
return builder.create();

補充:

1.dialog.create().show()
手動先建立 AlertDialog 實體,再顯示,如你要變更按鈕樣式、延遲顯示、或加入 EditText 等,就建議用 create()。如果只是單純顯示訊息則直接用 show() 即可。

AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Title").setMessage("Message");

AlertDialog alert = builder.create(); // 手動建立
alert.show();

// 之後可以控制按鈕
alert.getButton(AlertDialog.BUTTON_POSITIVE).setTextColor(Color.RED);

dialog.setCancelable(true); // 點擊對話框以外可取消顯示
dialog.setCancelable(false); // 必須按按鈕才能關閉

DatePickerDialog 日期選擇器

要注意的是在Android(Java)的Calendar和DatePicker中,月份從0開始計數而不是從1開始,所以如果想讓它顯示出來的是正確的月份記得+1

Calendar calendar = Calendar.getInstance();
DatePickerDialog dialog = new DatePickerDialog(MainActivity.this, new DatePickerDialog.OnDateSetListener() {
    // 當日期選擇完畢並按下"OK"按鈕 的事件觸發處理
    @Override
    public void onDateSet(DatePicker datePicker, int y, int m, int d) {
        StringBuilder result = new StringBuilder();
        //m+1:在Android(Java)的Calendar和DatePicker中,月份從0開始計數而不是從1開始。
        result.append(y).append("-").append(m+1).append("-").append(d);
        Toast.makeText(MainActivity.this, result, Toast.LENGTH_SHORT).show();
    }
},calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH));
//取出當前年月日作為預設選項
dialog.show();

補充:

可限制只能選今天之後的日期(如生日不能選未來)

dialog.getDatePicker().setMinDate(System.currentTimeMillis());

限制只能選特定區間

// 限制最早日期為 2020/01/01
Calendar minDate = Calendar.getInstance();
minDate.set(2020, 0, 1); // 月份一樣是從 0 開始

// 限制最晚日期為 2025/12/31
Calendar maxDate = Calendar.getInstance();
maxDate.set(2025, 11, 31); // 12 月是 11

dialog.getDatePicker().setMinDate(minDate.getTimeInMillis());
dialog.getDatePicker().setMaxDate(maxDate.getTimeInMillis());


TimePicker 時間選擇器

TimePicker有兩種顯示樣式,圓盤或是滾輪式,可以在程式碼中自訂

Calendar calendar = Calendar.getInstance();
//TimePicker 時間選擇器
//android.R.style.Theme_Holo_Light_Dialog_NoActionBar 顯示樣式(Spinner(滾輪))
//android.R.style.Theme_DeviceDefault_Light_Dialog     顯示樣式(圓形時鐘)
TimePickerDialog dialog = new TimePickerDialog(MainActivity.this, android.R.style.Theme_Holo_Light_Dialog_NoActionBar,
                                                new TimePickerDialog.OnTimeSetListener() {
    // 當時間選擇完畢並按下"OK"按鈕 的事件觸發處理
    @Override
    public void onTimeSet(TimePicker timePicker, int h, int m) {
        StringBuilder result = new StringBuilder();
        //格式化時間並補零
        String timeStr = String.format("%02d:%02d", h, m);
        Toast.makeText(MainActivity.this, result, Toast.LENGTH_SHORT).show();
    }
},   calendar.get(Calendar.HOUR_OF_DAY), // 24小時制的時
     calendar.get(Calendar.MINUTE),// 分
     true);// 是否使用24小時制,true = 24小時制,false = 12小時制
     //取出當前時間作為預設選項
dialog.show();


以下是這篇文章用到元件所需要的import

// 📅 日期與時間用
import java.util.Calendar;
import java.util.Timer;
import java.util.TimerTask;
import android.app.DatePickerDialog;
import android.app.TimePickerDialog;
import android.widget.DatePicker;
import android.widget.TimePicker;

// 🎲 其他功能
import java.util.Random; // 用於亂數生成

// 📦 Dialog 相關
import android.content.DialogInterface;
import androidx.appcompat.app.AlertDialog;

// 🍞 UI 提示
import android.widget.Toast;
import java.util.Random;//亂數計算 非Dialog
import android.content.DialogInterface;
import java.util.Timer;
import java.util.TimerTask;
import android.app.DatePickerDialog;
import android.widget.DatePicker;
import java.util.Calendar;
import android.app.TimePickerDialog;
import android.widget.TimePicker;

上一篇
Day 18.TextWatcher
下一篇
Day 20.SharedPreferences
系列文
Android 新手的 30 天進化論:從初學者到小專案開發者21
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言