[Android] 動態更新Activity所管理的Dialog-以TimePickerDialog為例


Activity如何有效管理Dialog一文中,介紹了Activity將系統執行過程中建立的Dialog物件進行儲存管理,以方便程式開發者進行操作,例如:顯示(showDialog)、隱藏(dismissDialog)等。由於Dialog都是由Activity代為保存管理,一但Dialog透過onCreateDialog建立之後,往後系統操作此Dialog時都會重覆利用該物件,但假設一種情況,萬一所呼叫的Dialog需要根據不同條件(例如:系統的狀態、時間等等)而動態調整Dialog顯示的內容的話,這樣的機制好像就無法支援,除非針對每一種條件都建立一個Dialog,但這樣的程式將十分難維護。


動態顯示Dialog內容的機制:覆寫onPrepareDialog()

為了支援Dialog內容動態顯示,Activity在透過showDialog(id)顯示對應id的Dialog物件之前,會先呼叫onPrepareDialog(id, dialog, args),這是唯一在Dialog顯示之前會被呼叫的函式,因此任何Dialog動態調整機制都必須在此實作,實作方式與onCreateDialog十分相似,先透過switch條件式以id參數決定是哪個Dialog,再應用dialog參數對此物件進行內容調整(如果有需要),以下將以TimePickerDialog為例,來說明動態顯示Dialog內容的機制。

範例情境:

系統畫面將有一個Button與TextView,當Button按下時會顯示一個TimePickerDialog,它必須在每次被呼叫時顯示當下時間;TextView則顯示User藉由TimePicker所設定的時間。



程式碼說明:

一、撰寫View描述xml檔,包含了Button與TextView


二、宣告變數,包含TimePickerDialog靜態id、當下時間和TextView參考
//current time
private int hour;
private int min;
//TextView reference
private TextView timeTxt;
//Time picker dialog's id
private static final int TIME_PICKER_DIALOG = 0;
三、註冊Button click listener,當按下時顯示time picker dialog
//取得Layout物件參考
Button showBtn = (Button)findViewById(R.id.show_btn);
timeTxt = (TextView)findViewById(R.id.time_txt);

//註冊showBtn click listener
showBtn.setOnClickListener(new OnClickListener(){
  @Override
  public void onClick(View v){
    showDialog(TIME_PICKER_DIALOG);
  }
});
四、實作onCreateDialog
@Override
protected Dialog onCreateDialog(int id, Bundle args){
  switch(id)
  {
    case TIME_PICKER_DIALOG:
    return new TimePickerDialog(this,
                                timeSetListener,
                                hour,min,false);
  }
  return null;
}
五、實作onPrepareDialog(),當TimePickerDialog被呼叫時,系統會呼叫其updateTime(hour,min),使其顯示目前當下時間
/**在Dialog.show()之前被呼叫的函式(取得當下時間)*/
@Override
protected void onPrepareDialog(int id, Dialog dialog, Bundle args){
 switch(id)
 {
  case TIME_PICKER_DIALOG:
    Log.d("DEBUG", "get current time!");
    TimePickerDialog timePicker = 
                               (TimePickerDialog)dialog;
    timePicker.updateTime(
        Calendar.getInstance().get(Calendar.HOUR_OF_DAY),
        Calendar.getInstance().get(Calendar.MINUTE)
                     );
    break;
 }
}
六、實作OnTimeSetListener,將TextView顯示使用者所選定的時間
TimePickerDialog.OnTimeSetListener timeSetListener=
    new TimePickerDialog.OnTimeSetListener(){
  @Override
  public void onTimeSet(TimePicker v, int h, int m){
   //取得user所選擇的時間
   hour = h;
   min = m;
   //更新time text
   updateTimeText();
  }
};

/**更新文字顯示(使用者目前所選擇的時間)*/
private void updateTimeText(){
  timeTxt.setText(
  getDisplayFormat(hour)+":"+
  getDisplayFormat(min)
  );
}

/**調整時間的格式*/
private String getDisplayFormat(int time){
  if(time<10){
    return "0"+String.valueOf(time);
  }else{
    return String.valueOf(time);
  }
}
完成上述步驟,每當TimePickerDialog被要求顯示時,其預設的顯示時間將會是當下時間(見下圖),只需要透過實作onPrepareDialog就可以達到動態更新Dialog畫面(上述範例如果沒有實作onPrepareDialog,TimePicker的預設時間將會是第一次建立的時間),讓Activity統一管理Dialog機制更為彈性、易用。

留言

這個網誌中的熱門文章

【海外婚紗】道具行李篇

[Android] layout_weight的妙用-讓View的大小以百分比率顯示(proportionate size)