Android 對話方塊相關總結
常用的對話方塊相關的有:AlertDialog,ProgressDialog,自定義的對話方塊(自定義的對話方塊的長寬設定需要注意),還有任意位置在其他應用上都可以彈出的對話方塊。其中任意位置在其他應用上都可以彈出的對話方塊見另一篇博文:點選跳轉。該博文的demo放在gihub上:點選跳轉。只有“將事件傳遞迴對話方塊的宿主”的例子在module:”passEventToHost”裡,其他都在dialog裡。
1.純粹的 AlertDialog以及設定位置
AlertDialog對話方塊是非常常用的對話方塊,一般又一個頭部,中間的說明文字和下面的按鈕組成。按鈕的數量可以是:1、2或3。注意的是,下面按鈕中,最前面到的那個按鈕,在Android的不同版本中,位置是不同的。
下面給出程式碼:
AlertDialog.Builder dialog = new AlertDialog.
Builder(MainActivity.this);
dialog.setTitle("對話方塊最上面的字");//對話方塊最上面的字
dialog.setMessage("對話方塊中部的字");//對話方塊中部的字
dialog.setCancelable(false);//如果是false,點選其他位置或者返回鍵無效,這個地方預設為true
//以下為對話方塊最下面的選擇項
dialog.setPositiveButton("右邊" , new DialogInterface.
OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(MainActivity.this, "右邊", Toast.LENGTH_SHORT).show();
}
});
//需要第二個按鈕才新增如下的setNegativeButton()
dialog.setNegativeButton("左邊", new DialogInterface.
OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(MainActivity.this, "左邊", Toast.LENGTH_SHORT).show();
}
});
//需要第三個按鈕時,才新增如下的setNeutralButton(),android老版本是在中間,比如4.0,在新版本是在前面,沒有研究從哪個版本開始變的
dialog.setNeutralButton("前面", new DialogInterface.
OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(MainActivity.this, "前面", Toast.LENGTH_SHORT).show();
dialog.dismiss();
}
});
dialog.show();
在Android 8.0 模擬器上執行效果:
2. ProgressDialog和自定義對話方塊
雖然,ProgressDialog官方在Androidd 8.0中已經棄用它了:“This class was deprecated in API level 26.“,但是實際用Android 8.0模擬器執行並沒有出現問題。而且官網沒有給出效果相同的直接代替的類。只是建議用別的東西代替,如ProgressBar。
下面給出程式碼:
ProgressDialog progressDialog = new ProgressDialog
(MainActivity.this);
progressDialog.setTitle("對話方塊上部的字");
progressDialog.setMessage("正在載入.....");
progressDialog.setCancelable(true);//如果是false,點選其他位置或者返回鍵無效,預設為true
progressDialog.show();
//progressDialog.dismiss();//此句讓progressDialog消失
在Android 8.0 模擬器上執行效果:
自定義對話方塊
下面給出一個簡單的,避開棄用progressDialog問題的方法:自定義對話方塊。通過getInflater.inflate(R.layout.dialog_layout, null)獲取View;通過builder.setView()給對話方塊設定view。這樣設定的Dialog寬度始終會如右圖下圖所示,而高度是wrap_content且有一個最小值,不會比那個值小,在
佈局檔案dialog_layout.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="20dp"
android:layout_marginStart="20dp"
android:layout_marginTop="15dp"
android:orientation="horizontal">
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
android:id="@+id/message"
android:layout_marginLeft="20dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:text="message"
android:textSize="17sp"/>
</LinearLayout>
</LinearLayout>
java程式碼如下,通過message.setText()改變下方顯示文字, builder.setTitle()設定上方顯示文字。
AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
LayoutInflater inflater = getLayoutInflater();
View dialogView = inflater.inflate(R.layout.dialog_layout, null);
builder.setView(dialogView).create();
builder.setTitle("進度");
TextView message = dialogView.findViewById(R.id.message);
message.setText("進度:%10");
builder.show();
下面對比一下,效果基本與ProgressDialog一致:
3. 自定義對話方塊(考慮wrap_content時的大小問題)
自定義對話方塊,就是自己寫一個佈局,讓對話方塊載入佈局,並且能監聽這個佈局裡面的點選事件,並且對話方塊可以響應點選消失。需要注意的是,有時候自定義的根佈局高和寬是wrap_content,這時定義的對話方塊長寬會失效,下面是考慮到這種問題的自定義對話方塊。但是比較麻煩,如果根佈局大小可以寫死,就不需要考慮這個問題
首先寫一個對話方塊的佈局:my_dialog.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@color/colorAccent"
android:orientation="vertical">
<TextView
android:layout_width="300dp"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="自定義對話方塊"
android:textSize="20sp"/>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="20dp">
<Button
android:id="@+id/leftBt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="左按鈕"/>
<Button
android:id="@+id/rightBt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="右按鈕"/>
</LinearLayout>
</LinearLayout>
設計對話方塊的style,目的是去控制對話方塊長寬,並且避免出現一些上部陰影,下面是新增在styles.xml中的程式碼,其中windowIsFloating讓java程式碼部分控制大小生效,windowNoTitle避免出現一些上部陰影:
<style name="style_dialog" parent="android:style/Theme.Dialog">
<item name="android:windowNoTitle">true</item>
<item name="android:windowIsFloating">true</item>
</style>
在java程式碼部分會用到上面的檔案,注意一點:匯入的AlertDialog語句是:import android.support.v7.app.AlertDialog;(不要匯入錯誤成另一個)
//獲取自定義佈局view例項
View layout = LayoutInflater.from(this).inflate(R.layout.my_dialog, null);
//在對話方塊里加載佈局:setView()方法
final AlertDialog.Builder dialog = new AlertDialog.
Builder(MainActivity.this,R.style.style_dialog);
dialog.setCancelable(false)//如果是false,點選其他位置或者返回鍵無效,這個地方預設為true
.setView(layout);//這裡載入佈局
final AlertDialog alert = dialog.create();
//設定對話方塊的寬和高(注意,設定長寬還需要設定R.style.style_dialog,否則會出現很多問題),
//並且如果需要設定佈局大小,而不是wrap_content,那麼需要在佈局的子項裡面設定大小,
//直接在最外層設定是無效的
Window window = alert.getWindow();
window.getDecorView().setPadding(0, 0, 0, 0);//void setPadding (int left, int top,int right,int bottom)
WindowManager.LayoutParams lp = window.getAttributes();
lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
window.setAttributes(lp);
window.setGravity(Gravity.CENTER);//對話框出現的位置
//按鈕監聽事件
Button btLeft, btRight;
btLeft = layout.findViewById(R.id.leftBt);
btRight = layout.findViewById(R.id.rightBt);
btLeft.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//這裡寫左按鈕點選響應事件
Toast.makeText(MainActivity.this, "左按鈕", Toast.LENGTH_SHORT).show();
alert.dismiss();//讓對話方塊消失
}
});
btRight.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//這裡寫右按鈕點選響應事件
Toast.makeText(MainActivity.this, "右按鈕", Toast.LENGTH_SHORT).show();
alert.dismiss();//讓對話方塊消失
}
});
alert.show();
}
在擬器上執行效果:
4.單選列表對話方塊
新增builder.setItems()即可,setItems第一個引數是顯示資料的陣列,第二個是點選監聽DialogInterface.OnClickListener物件。也可以使用 setAdapter() 指定一個列表。 這樣一來,您就可以使用 ListAdapter 以動態資料(如來自資料庫的資料)支援列表。
String[] arr={"第一項","第二項","第三項"};
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("單選列表對話方塊")
.setItems(arr, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// which是點選列表位置
Toast.makeText(MainActivity.this, which+"", Toast.LENGTH_SHORT).show();
}
});
builder.create().show();
}
效果是這樣的:
5.多選列表對話方塊
需要定義一個List物件儲存選定內容,在點選確定時讀取。依靠setMultiChoiceItems()方法實現多選列表對話方塊。
List <String>mSelectedItems;//用於多選列表對話方塊選擇項的暫時儲存
String[] arr={"第一項","第二項","第三項"};
mSelectedItems = new ArrayList(); //用來存放被選中的項
AlertDialog.Builder builder = new AlertDialog.Builder(this);
// Set the dialog title
builder.setTitle("多選列表對話方塊")
// Specify the list array, the items to be selected by default (null for none),
// and the listener through which to receive callbacks when items are selected
.setMultiChoiceItems(arr, null,
new DialogInterface.OnMultiChoiceClickListener() {
@Override
public void onClick(DialogInterface dialog, int which,
boolean isChecked) {
if (isChecked) {
// 如果選擇一項,那麼在選定的項中新增此項
mSelectedItems.add(which+"");
} else if (mSelectedItems.contains(which)) {
// 如果取消選擇,那麼在選定的項中移除此項
mSelectedItems.remove(Integer.valueOf(which));
}
}
})
// Set the action buttons
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int id) {
//確定
String result="";
for(String str:mSelectedItems){
result+=str;
}
//這裡輸出被選中項
Toast.makeText(MainActivity.this, result, Toast.LENGTH_SHORT).show();
}
})
.setNegativeButton("cancel", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int id) {
//取消
}
});
builder.create().show();
效果如下:
6.全屏的對話方塊
1.狀態列消失,螢幕全部佔滿的對話方塊
建議使用Dialog而不是AlertDialog,因為AlertDialog自帶的一些屬性使全屏變得比Dialog麻煩一些。Dialog與AlertDialog程式碼上的區別,主要是它沒有Builder,而是直接在Dialog上對對話方塊屬性進行設定。而要讓Dialog全屏是非常簡單的,只需要在例項化Dialog物件時像這樣傳遞引數即可。注意,這樣的話,螢幕上方狀態列也會消失,對話方塊佔據整個螢幕(除虛按鍵)。
Dialog dialog = new Dialog(this,android.R.style.
Theme_Light_NoTitleBar_Fullscreen);
完整的一個自定義佈局的全屏對話方塊程式碼:
public showDialog(Activity activity){
Dialog dialog = new Dialog(activity,
android.R.style.Theme_Light_NoTitleBar_Fullscreen);//第二引數為關鍵程式碼
View view = LayoutInflater.from(activity).
inflate(R.layout.diag_list, null, false);//diag_list是對話方塊的佈局檔案
dialog.setContentView(view);
//這裡區別於AlertDialog,Builder的setView(View)
dialog.show();
}
下面在提供一種狀態列不消失的全屏對話方塊的方法:
2.讓狀態列顯示的全屏對話方塊
需要設定對話方塊長寬都是match_parent,因為預設是wrap_content
dialog.getWindow().setLayout(WindowManager.LayoutParams.MATCH_PARENT, WindowManager
.LayoutParams.MATCH_PARENT);
需要設定Dialog的背景,因為它預設背景會距離螢幕上下左右各8dp
dialog.getWindow().setBackgroundDrawable(null);
//注意,以上寫法會使dialog背景透明,可以在對話方塊佈局檔案中設定佈局背景色。
//或像下面一樣,設背景色為白色
//dialog.getWindow().setBackgroundDrawable(new
//ColorDrawable(getResources().getColor(android.R.color.white)));
以上兩步可以使Dialog全屏(不包含狀態列),下面一個完整例子:
public void showDialog(Activity activity) {
Dialog dialog = new Dialog(activity);//一個引數
View view = LayoutInflater.from(activity).inflate(R.layout.diag_list, null, false);
dialog.setContentView(view);
dialog.getWindow().setLayout(WindowManager.LayoutParams.MATCH_PARENT, WindowManager
.LayoutParams.MATCH_PARENT);
dialog.getWindow().setBackgroundDrawable(new ColorDrawable(activity.getResources().getColor(android.R.color.white)));
dialog.show();
}