編輯:關於Android編程
Dialog
是Android
中對話框相關的類,起到相關提示的作用。
Dialog
在Android 中主要分為以下幾類:
AlertDialog
:警告對話框(提示對話框) ProgressDialog
:進度對話框 DatePickerDialog
:日期選擇對話框 TimerPickerDialog
: 時間選擇對話框 自定義對話框
下面將按照如上所分類,進行一一介紹。
AlertDialog
繼承 Dialog
,該對象對於常用的一些對話框進行了封裝。
需要注意的是AlertDialog
存在兩種實現並對應的存在於兩個不同的包,
android.app.AlertDialog
。該包中的AlertDialog
並沒有對不同版本的系統進行適配。在不同的手機系統上會顯示不同的樣式。(不推薦)。 v7包android.support.v7.app.AlertDialog
。該包中的AlertDialog
是根據google 推出的Material Desgin
進行設計的,並對低版本的系統進行了適配。支持系統版本到7(Android 2.1 )以上。(推薦)
下面都將使用v7版本的AlertDialog
AlertDialog
的使用分為以下幾步:
AlertDialog.Builder
對象,該對象能創建AlertDialog
。 調用Builder
對象的方法設置圖標、標題、內容、按鈕等。setTitle()
:為對話框設置標題 setIcon ()
:設置圖標 setMessage ()
:設置要顯示的信息 setPositiveButton ()
:設置確定按鈕 setNegativeButton ()
: 設置取消按鈕 setNeutralButton ()
:設置中立按鈕 調用Builder
對象的create()
方法創建AlertDialog
對話框。 調用AlertDialog
的show()
方法來顯示對話框 調用AlertDialog
的dimiss()
方法銷毀對話框。
下面就根據上面的步驟,來創建AlertDialog
方法。
public void dialog1(View view){
// 簡單的AlertDialog
// 1 . 創建AlertDialog 對象
// 注意 Dialog 的Builder的創建雖然傳入的是Context,其實是多態,此處必須傳入Activity對象
AlertDialog.Builder builder = new AlertDialog.Builder(this);
// 2. 通過builder 設置一些常用的屬性
// 設置圖標
builder.setIcon(R.mipmap.ic_launcher);
// 設置標題
builder.setTitle("提示");
//設置提示消息
builder.setMessage("這是一個基礎的AlertDialog");
builder.setPositiveButton("確定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
//點擊確定按鈕之後的回調
Toast.makeText(AlertDialogActivity.this, "確定", Toast.LENGTH_SHORT).show();
}
});
builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
//點擊取消按鈕之後的回調
}
});
builder.setNeutralButton("中間", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
//點擊中間的按鈕的回調
}
});
//3 .通過Builder 的 create方法創建AlertDialog;
AlertDialog dialog = builder.create();
// 4 . 顯示對話框
dialog.show();
}
看一下效果
有以下幾點需要注意:<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4NCjxjb2RlPkFsZXJ0RGlhbG9nPC9jb2RlPrrNPGNvZGU+QnVpbGRlcjwvY29kZT61vMjrtcS2vMrHPGNvZGU+YW5kcm9pZC5zdXBwb3J0LnY3LmFwcC5BbGVydERpYWxvZzwvY29kZT6hoyDIt7aoo6zIoc/7us3W0LzkyP249rC0xaW1xL3Tv9q72LX3o6y147v3yrHErMjPtry199PDwcs8Y29kZT5kaW1pc3MoKTwvY29kZT63vbeoo6zL+dLUztLDx87e0OjK1rav0v6y2Mv7oaMg0ruw49TayrnTw9bQo6yyu7vhyrnTw9bQvOTEx7j2sLTFpaGjtrzKx8G9uPawtMWl1+O5u6O6yKHP+7rNyLe2qKOsyLe2qNTa09KjrMihz/vU2tfzoaO31rHwttTTpsG9uPa84Mz9PGNvZGU+c2V0UG9zaXRpdmVCdXR0b248L2NvZGU+us08Y29kZT5zZXROZWdhdGl2ZUJ1dHRvbjwvY29kZT6ho9OizsS1pbTK0uLOqrv9vKu1xLrNz/u8q7XEoaMgtLS9qDxjb2RlPkRpYWxvZzwvY29kZT7L5Mi70OjSqrXEysc8Y29kZT5Db250ZXh0PC9jb2RlPiy1q7HY0Ou0q8jrPGNvZGU+QWN0aXZpdHk8L2NvZGU+ttTP86GjDQo8cD7I57n7uduy7NfQz7i1xLvht6LP1jxjb2RlPmJ1aWxkZXI8L2NvZGU+tcQ8Y29kZT5zZXhYWFg8L2NvZGU+t723qKOst7W72LXEyNTIu8rHPGNvZGU+QnVpbGRlcjwvY29kZT621M/zoaPEx8O0ztLDx7/J0tTQ3rjEtPrC69auuvPI58/Co7o8L3A+DQo8cHJlIGNsYXNzPQ=="brush:java;">
AlertDialog dialog = new AlertDialog.Builder(this)
.setIcon(R.mipmap.ic_launcher)
.setTitle("提示")
.setMessage("這是一個基礎的AlertDialog")
.setPositiveButton("確定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
//點擊確定按鈕之後的回調
Toast.makeText(AlertDialogActivity.this, "確定", Toast.LENGTH_SHORT).show();
}
})
.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
//點擊取消按鈕之後的回調
}
})
.setNeutralButton("中間", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
//點擊中間的按鈕的回調
}
}).create();
類似一條鏈式的創建Dialog
對象。
因為AlertDialog
繼承Dialog
,所以他擁有Dialog
的特性。(該特性對於所有的對話框都適用)
其中幾個常用的方法:
setCancelable(boolean flag)
:當點擊返回鍵的時候,Dialog是否消失。 true 表示點擊返回鍵提示框消失。 false表示不消失,即點擊返回無效果。 setCanceledOnTouchOutside (boolean cancel)
點擊對話框以外的區域時,對話框是否消失。true 表示點擊以外的區域消失,false表示不消失。
// 點擊返回不會取消對話框
dialog.setCancelable(false);
// 觸摸對話框以外的區域不會消失
dialog.setCanceledOnTouchOutside(false);
注意:該方法是
Dialog
的方法,不是Builder
中的方法。
實現單選功能對話框有兩種實現方式,通過兩個方法setItems
和setSingleChoiceItems
。
setItems
:通過該方法實現對話框,無需點擊確定,直接點擊條目之後立即消失,同時調用相應的回調。 setSingleChoiceItems
:普通的單選效果,帶有圓圈,點擊確定之後隱藏。
首先看一下兩個的效果圖:
- setItems()
方法實現單選
final String[] sex = {"男","女"};
AlertDialog dialog = new AlertDialog.Builder(this)
.setItems(sex, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// which 表示的 點擊的索引。
Toast.makeText(AlertDialogActivity.this, sex[which], Toast.LENGTH_SHORT).show();
}
}).create();
dialog.show();
setItems(CharSequence[] items, final OnClickListener listener)
: 第一個參數為顯示不同數據的數組。第二個方法為選擇之後的回調。
setSingleChoiceItems
實現:
public void choice_single(View view){
final String[] sex = {"男","女"};
AlertDialog dialog = new AlertDialog.Builder(this)
.setSingleChoiceItems(sex, 0,new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// which 表示的 點擊的索引。
Toast.makeText(AlertDialogActivity.this, sex[which], Toast.LENGTH_SHORT).show();
//保存狀態
}
})
.setPositiveButton("確定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// 確定操作
//通過在上一個onClick方法中的回調的記錄,進行對應操作。
}
})
.create();
dialog.show();
}
setSingleChoiceItems(CharSequence[] items, int checkedItem,final OnClickListener listener)
: 第一個參數表示數據數組,第二個參數表示默認選中第幾條,第三個參數為借口回調。
setItems
方式實現無法修改,只能選擇一次,選中之後對話框就會消失。 setSingleChoiceItems
,可以設置默認的選中條目,多次選擇,選中之後不會消失,直到點擊確定等隱藏對話框的操作。 兩者選中事件的回調相同,都是在他們的參數中的回調對象進行操作。
AlertDialog.Builder
中存在方法setMultiChoiceItems(CharSequence[] items, boolean[] checkedItems, DialogInterface.OnMultiChoiceClickListener listener)
設置多選對話框。
CharSequence[] items
:可選的條目的數組數據。 boolean[] checkedItems
:默認顯示的狀態,與條目一一對象,false表示不選中,true表示默認選中。 DialogInterface.OnMultiChoiceClickListener listener
:條目選擇產生變化之後的回調
看一下效果:
具體代碼
final String[] like = {"足球","籃球","乒乓球","排球"};
final boolean[] check = {false,false,true,true};
AlertDialog dialog = new AlertDialog.Builder(this)
.setMultiChoiceItems(like, check, new DialogInterface.OnMultiChoiceClickListener() {
@Override
public void onClick(DialogInterface dialog, int which, boolean isChecked) {
// which 數據變化的索引 isChecked 表示變化的結果
// 根據變化修改數據
check[which] = isChecked;
}
})
.setPositiveButton("確定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// 確定操作
//根據check 中的true 和 flase 進行處理不同結果。
String select = "";
for(int i = 0;i
setMultiChoiceItems
中的OnMultiChoiceClickListener()
,數據變化時回調此方法,我們需要在此方法中保存修改的數據。
ProgressDialog 進度對話框
ProgressDialog
也是繼承於Dialog
,但其擴展了緩沖加載提示的功能。
總共分為兩種樣式,一種是圓形轉圈的加載,一種是水平進度條(帶有加載進度)的效果。
看一下效果:
圓形加載對話框
看一下demo
/**
* 圓形加載對話框
* @param view
*/
public void progress_circle(View view){
final ProgressDialog pd = new ProgressDialog(this);
// 進度條為水平旋轉
pd.setProgressStyle(ProgressDialog.STYLE_SPINNER);
// 設置點擊返回不能取消
pd.setCancelable(false);
//設置觸摸對話框以外的區域不會消失
pd.setCanceledOnTouchOutside(false);
// 設置提示的title的圖標,默認是沒有的,如果沒有設置title的話只設置Icon是不會顯示圖標的
pd.setIcon(R.mipmap.ic_launcher);
// 設置標題
pd.setTitle("提示");
pd.setOnDismissListener(new DialogInterface.OnDismissListener() {
@Override
public void onDismiss(DialogInterface dialog) {
// dimiss的監聽
}
});
pd.setOnCancelListener(new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
//cancel
}
});
pd.setMessage("這是一個圓形進度條");
pd.show();
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(5000);
//pd.cancel();
pd.dismiss();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
直接 new
出ProgressDialog
,並沒有創建什麼Builder
類。 通過設置setProgressStyle
為ProgressDialog.STYLE_SPINNER
,使其顯示圓形加載效果。 pd.dismiss()
和pd.cancel()
方法都能夠隱藏加載對話框。
cancel()
表示隱藏對話框,對話框並不會被銷毀。會回調setOnCancelListener
. dismiss()
:銷毀對話框,回調setOnDismissListener
。
推薦使用
dismiss()
方法。因為,如果調用了cancel
,在activity
結束時,仍要手動調用dismiss
。不然,dialog
如果沒有銷毀,則會導致內存溢出。
水平加載對話框
/**
* 水平加載進度對話框
* @param view
*/
public void progress_horizontal(View view){
final ProgressDialog pd = new ProgressDialog(this);
// 設置水平進度條
pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
// 設置點擊返回不能取消
pd.setCancelable(false);
//設置觸摸對話框以外的區域不會消失
pd.setCanceledOnTouchOutside(false);
// 設置提示的title的圖標,默認是沒有的,如果沒有設置title的話只設置Icon是不會顯示圖標的
pd.setIcon(R.mipmap.ic_launcher);
// 設置標題
pd.setTitle("提示");
// 默認為100
pd.setMax(100);
pd.setMessage("這是一個水平進度條");
pd.show();
new Thread(new Runnable() {
@Override
public void run() {
int i = 0;
while (i < 100) {
try {
Thread.sleep(200);
// 每次增加 1%
pd.incrementProgressBy(1);
i++;
} catch (Exception e) {
}
}
pd.dismiss();
}
}).start();
}
設置一個線程,通過線程沒個200ms使進度值+1,最後銷毀
dialog
。
設置樣式:setProgressStyle
為ProgressDialog.STYLE_HORIZONTAL
設置總的進度:pd.setMax()
,整形,默認為100。 動態改變進度:pd.incrementProgressBy(1);
,改變當前進度值,傳入的參數為遞增量。
DataPickerDialog 日期選擇對話框
Android 提供的原生控件,使用起來比較簡單,但因為其沒有對不同系統做適配,所以在不同系統上顯示可能不同。只做了解即可。一般都是自定義日期對話框。
效果
注意:該效果是在Android5.0和以上系統上顯示的效果。具體適配會在後面提到。
使用方式
/**
* 日期選擇器
* @param view
*/
public void dialog_date(View view){
// 年,天,時,分都是從 1 開始 月從1 開始
// 獲取系統當前時間
Calendar instance = Calendar.getInstance();
int year = instance.get(Calendar.YEAR);
int month = instance.get(Calendar.MONTH); // 該方法month 從0 開始
int day = instance.get(Calendar.DAY_OF_MONTH);
// 構造dialog
DatePickerDialog dialog = new DatePickerDialog(this,new DatePickerDialog.OnDateSetListener() {
@Override
public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) {
// 獲取到的month 需要+1 獲取正確的月份
Toast.makeText(AlertDialogActivity.this, year+"-"+monthOfYear+"-"+dayOfMonth, Toast.LENGTH_SHORT).show();
}
},year,month,day);
dialog.show();
}
通過
Calendar
獲取系統當前時間,並通過DatePickerDialog
的構造方法傳入系統當前時間和相應的數據回調。最後在顯示。
DatePickerDialog()
構造方法有5個參數:
- 當前Activity
- onDateSetListener()
:數據的回調,在點擊確定是將數據作為參數回調onDateSet
方法。
- year
, 年
- month
,注意+1和-1
- day
,天
有以下幾點注意:
在JAVA的時間中,無論是當前的Calendar
還是DataPicker
,他們的年,天,時,分都是從0開始的,也就是直接獲取值顯示即可。而月是從0開始的,即我們需要對數據進行+1或-1操作。
如果日期是2016-6-15,則傳入的參數為,2016,5,15 如果onDataSet
回調的日期是2016,5,15。則在顯示時需要對月份+1 ,即2016,6(5+1),15 顏色的設置:可以看到起彈出的大部分是粉紅色,我們可以自定義粉紅色區域的顏色。該顏色獲取的是我們對應用設置的主題中的
TimePicker 時間選擇器
該控件的使用和
DatePickerDialog
的使用基本類似。
看一下效果
注意:該效果是在Android5.0和以上系統上顯示的效果。具體適配會在後面提到。
/**
* 時間選擇器
* @param view
*/
public void dialog_time(View view){
// 獲取系統時間
Calendar instance = Calendar.getInstance();
int hour = instance.get(Calendar.HOUR_OF_DAY);
int minute = instance.get(Calendar.MINUTE);
// 時間對話框
TimePickerDialog dialog = new TimePickerDialog(this, new TimePickerDialog.OnTimeSetListener() {
@Override
public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
Toast.makeText(AlertDialogActivity.this, hourOfDay+"-"+minute, Toast.LENGTH_SHORT).show();
}
},hour,minute,true);
//顯示
dialog.show();
}
TimePickerDialog
的有5個參數
- 當前Activity
的對象
- onTimeSetListener
,數據回調。
- hour
:小時
- minute
:分
- is24hourView
: false
:不使用24小時制。true
:使用24小時表示。
自定義Dialog
在平常的項目中,因為系統提供的
dialog
無法很好的適配不同的版本(樣式不同),通常自定義Dialog
實現相應功能。
實現的步驟:
編寫自定義的布局 自定義類繼承Dialog
並實現構造方法。 設置dialog
的主題。 加載自定義布局 使用setContentView
設置到dialog
中。 查找相應控件並編寫邏輯。
看一下效果
編寫自定義布局dialog_simple.xml
很多需求模仿IOS 實現外框是一個圓角矩形的形式。Dialog
並沒有提供對應的方法,我們需要從自定義布局上,設置它的背景為圓角矩形。
圓角矩形
shape
資源shape_dialog_psd_bg.xml
下面就是編寫
CustomDialog
類
/**
* 簡單的對話框
* Created by MH on 2016/6/15.
*/
public class SimpleDialog extends Dialog implements View.OnClickListener {
public SimpleDialog(Context context) {
// 注意,在此處設置樣式
super(context,R.style.CustomDialog);
// 設置我們的布局到dialog中
setContentView(R.layout.dialog_simple);
// 初始化布局
initView();
}
private void initView() {
findViewById(R.id.dialog_simple_cancel).setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.dialog_simple_cancel:
// 對應的點擊事件
this.dismiss();
break;
}
}
}
在如上類中,關鍵的幾步如下:
重寫構造方法,我們選擇只有一個參數的。 構造方法調用父類構造方法並傳入了dialog
的樣式。 setContentView()
設置自定義布局到dialog
中。 查找控件並編寫相應的邏輯
其中需要注意的一點為設置樣式,該樣式設置的目的是為了統一不同系統版本下顯示的樣式,如果不設置,在低於Android5。0的系統下會爆炸。。。
在此定義的樣式一般為
自定義
Dialog
大概就這麼多,復雜的無非就是界面復雜點,邏輯復雜點那麼多。
Dialog 設置動畫
看一下效果圖
下面就開始實現,定義動畫需要通過
xml
文件來編寫動畫
dialog_anim_enter.xml
進入的動畫
dialog_anim_exit.xml
離開動畫
如果對動畫不是太熟悉的,可以看我之前的博客Android動畫之視圖動畫和屬性動畫
在這裡需要注意,雖然是相對父布局,但仍然是我們顯示的dialog的左上角為0坐標開始偏移的,效果是相對於本身的動畫。我猜測應該是
dialog
外層包裹了另一個和他一樣大小的布局。
編寫動畫的樣式
通過dialog.getWindow().setWindowAnim(int resId)
方法設置動畫
/**
* dialog設置動畫
*/
public void dialog_anim(View view){
SimpleDialog dialog = new SimpleDialog(this);
// 設置動畫
dialog.getWindow().setWindowAnimations(R.style.DialogAnim);
dialog.show();
}
該動畫的設置方法對所有的
dialog
都適用,即之前系統提供的AlertDialog
都適用。
設置Dialog的大小
兩種實現方式:
第一種方式 通過
dialog.getWindow().setLayout(100,100);
設置大小。
第二種方式 通過
dialog.getWindow().getAttributes();
設置。
/**
* 設置大小
* @param view
*/
public void dialog_size(View view) {
SimpleDialog dialog = new SimpleDialog(this);
// // 第一種方式
// dialog.getWindow().setLayout(100,100);
// 第二種方式 獲取參數
WindowManager.LayoutParams params = dialog.getWindow().getAttributes();
// 設置高度
params.height = 100;
// 設置寬度
params.width = 100;
// 設置
dialog.getWindow().setAttributes(params);
dialog.show();
}
其實第一種方式,在其內部實現上也是通過第二種方式設置的。 第二種方式獲取到的params
,裡面包含了很多dialog
的顯示屬性,不是只要高度和寬度。
該大小的設置方法對所有的
dialog
都適用,即之前系統提供的AlertDialog
都適用。
該博客中的源碼已經更新到github,有需要者請移步。
這篇博客來介紹外觀模式(Facade Pattern),外觀模式也稱為門面模式,它在開發過程中運用頻率非常高,尤其是第三方 SDK 基本很大概率都會使用外觀模式。通過一個
事件分發android事件處理的時候 會根據事件發生的坐標,從父容器一直慢慢的發送到相關的所有的view 因此當都不處理的時候 事件傳遞的流程圖dispatchTouch
簡單拓展RadioButton控件使用如果不看這些,就直接下托RadioButton和CheckBox的區別:1、單個RadioButton在選中後,通過點擊無法變為未選
常用的Dialog有確認對話框,單選按鈕對話框,多選按鈕對話框,復選按鈕對話框另外還有自定義的對話框AlertDialog的常用方法setTitle:為對話框設置標題se