Android常用對話方塊大全——Dialog
唉!最近一直忙碌著寫專案以至於都沒有空出點時間來總結近期的學習,
記錄學習到的東西…現在正好有時間了就該好好記錄一下學習的過程了。
今天就來談談開發中經常用的到的一個控制元件——Dialog,對話方塊一般我們就用來提示一些資訊給使用者,
讓使用者自主選擇,或者在一些操作不可逆的情況下我們提示使用者是否繼續操作,
下面就讓我們一起來學習吧。老司機發車啦…
一:最簡單的對話方塊
AlertDialog dialog = new AlertDialog.Builder(this)
.setIcon(R.mipmap.icon)//設定標題的圖片
.setTitle("我是對話方塊")//設定對話方塊的標題
.setMessage("我是對話方塊的內容")//設定對話方塊的內容
//設定對話方塊的按鈕
.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(MainActivity.this, "點選了取消按鈕", Toast.LENGTH_SHORT).show();
dialog.dismiss();
}
})
.setPositiveButton("確定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(MainActivity.this, "點選了確定的按鈕", Toast.LENGTH_SHORT).show();
dialog.dismiss();
}
}).create();
dialog.show();
AlertDialog類中有一個靜態內部類Builder。所以可以看出對話方塊使用了一個建造者模式在呼叫函式的時候就可以一直直點點點鏈式呼叫。 需要注意的是:NegativeButton這個按鈕是在對話方塊的左邊,PositiveButton在對話方塊的右邊;如果你還想再加一個按鈕也是可以的只需要在呼叫
.setNeutralButton("第三個按鈕",listener)
即可。
二:列表對話方塊
當給使用者的選擇就那麼幾條路的時候,就可在對話方塊上放置一個列表供使用者自己選擇
final String items[] = {"我是Item一", "我是Item二", "我是Item三", "我是Item四"};
AlertDialog dialog = new AlertDialog.Builder(this)
.setIcon(R.mipmap.icon)//設定標題的圖片
.setTitle("列表對話方塊")//設定對話方塊的標題
.setItems(items, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(MainActivity.this, items[which], Toast.LENGTH_SHORT).show();
}
})
.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
})
.setPositiveButton("確定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
}).create();
dialog.show();
原始碼已經為我們預留好了設定方法,所以我們只需要呼叫
.setItems()
即可,第一個引數即要顯示item的陣列,第二個引數也就是點選item後的監聽事件還是so easy的。
三:單選列表對話方塊,這個與列表對話方塊差不對是一樣的只是它是單選
final String items[] = {"我是Item一", "我是Item二", "我是Item三", "我是Item四"};
AlertDialog dialog = new AlertDialog.Builder(this)
.setIcon(R.mipmap.icon)//設定標題的圖片
.setTitle("單選列表對話方塊")//設定對話方塊的標題
.setSingleChoiceItems(items, 1, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(MainActivity.this, items[which], Toast.LENGTH_SHORT).show();
}
})
.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
})
.setPositiveButton("確定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
}).create();
dialog.show();
.setSingleChoiceItems(items, 1, listener)
第一個引數:設定單選的資源陣列;第二個引數:設定預設選中哪一項。
四:既然有單選列表,那自然而然也就肯定有多選列表啦
final String items[] = {"我是Item一", "我是Item二", "我是Item三", "我是Item四"};
final boolean checkedItems[] = {true, false, true, false};
AlertDialog dialog = new AlertDialog.Builder(this)
.setIcon(R.mipmap.icon)//設定標題的圖片
.setTitle("多選對話方塊")//設定對話方塊的標題
.setMultiChoiceItems(items, checkedItems, new DialogInterface.OnMultiChoiceClickListener() {
@Override
public void onClick(DialogInterface dialog, int which, boolean isChecked) {
checkedItems[which] = isChecked;
}
})
.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
})
.setPositiveButton("確定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
for (int i = 0; i < checkedItems.length; i++) {
if (checkedItems[i]) {
Toast.makeText(MainActivity.this, "選中了" + i, Toast.LENGTH_SHORT).show();
}
}
dialog.dismiss();
}
}).create();
dialog.show();
.setMultiChoiceItems(items, checkedItems, listener)
//第一個引數:設定單選的資源;第二個引數:設定預設選中哪幾項(陣列);
五:或許上面幾種對話方塊的款式都不是你需要或者喜歡的,那你肯定就需要開始自定義了;原始碼為我們提供了一個.setView()
函式,這樣我們就可以自定義對話方塊顯示的內容了,如下程式碼:
View view = getLayoutInflater().inflate(R.layout.half_dialog_view, null);
final EditText editText = (EditText) view.findViewById(R.id.dialog_edit);
AlertDialog dialog = new AlertDialog.Builder(this)
.setIcon(R.mipmap.icon)//設定標題的圖片
.setTitle("半自定義對話方塊")//設定對話方塊的標題
.setView(view)
.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
})
.setPositiveButton("確定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
String content = editText.getText().toString();
Toast.makeText(MainActivity.this, content, Toast.LENGTH_SHORT).show();
dialog.dismiss();
}
}).create();
dialog.show();
上面程式碼中
half_dialog_view.xml
中我就放置了一個EditText;在這裡好多人在找自己佈局中的控制元件時候經常報NullpointException,原因也很簡單就是沒有使用載入的佈局.findViewbyId()
。到了這一步基本上就能滿足開發中80%的需求了,看官如果還不能滿足那別急慢慢往下看。
六:完全自定義的對話方塊
上面我們說了可以通過呼叫
.setView(view)
方法,自定義其顯示的內容;但是你會覺得這遠遠不夠我還想把他的標題或者底部按鈕給改了,那麼就需要來個完全自定義了,如下:
- 首先我們需要自定義Dialog的style,讓他自己本有的東西全部透明,然後在設定我們自己的內容就可以達到完全自定義的效果了。
<!--對話方塊的樣式-->
<style name="NormalDialogStyle">
<!--對話方塊背景 -->
<item name="android:windowBackground">@android:color/transparent</item>
<!--邊框 -->
<item name="android:windowFrame">@null</item>
<!--沒有標題 -->
<item name="android:windowNoTitle">true</item>
<!-- 是否浮現在Activity之上 -->
<item name="android:windowIsFloating">true</item>
<!--背景透明 -->
<item name="android:windowIsTranslucent">false</item>
<!-- 是否有覆蓋 -->
<item name="android:windowContentOverlay">@null</item>
<!--進出的顯示動畫 -->
<item name="android:windowAnimationStyle">@style/normalDialogAnim</item>
<!--背景變暗-->
<item name="android:backgroundDimEnabled">true</item>
</style>
<!--對話方塊動畫-->
<style name="normalDialogAnim" parent="android:Animation">
<item name="@android:windowEnterAnimation">@anim/normal_dialog_enter</item>
<item name="@android:windowExitAnimation">@anim/normal_dialog_exit</item>
</style>
- 接下來就可以為對話方塊設定我們自定義的style了.
/**
* 自定義對話方塊
*/
private void customDialog() {
final Dialog dialog = new Dialog(this, R.style.NormalDialogStyle);
View view = View.inflate(this, R.layout.dialog_normal, null);
TextView cancel = (TextView) view.findViewById(R.id.cancel);
TextView confirm = (TextView) view.findViewById(R.id.confirm);
dialog.setContentView(view);
//使得點選對話方塊外部不消失對話方塊
dialog.setCanceledOnTouchOutside(true);
//設定對話方塊的大小
view.setMinimumHeight((int) (ScreenSizeUtils.getInstance(this).getScreenHeight() * 0.23f));
Window dialogWindow = dialog.getWindow();
WindowManager.LayoutParams lp = dialogWindow.getAttributes();
lp.width = (int) (ScreenSizeUtils.getInstance(this).getScreenWidth() * 0.75f);
lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
lp.gravity = Gravity.CENTER;
dialogWindow.setAttributes(lp);
cancel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
dialog.dismiss();
}
});
confirm.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
dialog.dismiss();
}
});
dialog.show();
}
同樣我門通過呼叫這個
dialog.setContentView(view);
就可以設定我們自己的佈局了。所以現在關鍵就是碼我們的佈局了一起來看看效果圖
既然是自定義對話方塊,那麼就肯定要來弄一弄他的方方面面;
- 這裡使用到了一個工具類用來計算手機螢幕的寬高,如下程式碼:
public class ScreenSizeUtils {
private static ScreenSizeUtils instance = null;
private int screenWidth, screenHeight;
public static ScreenSizeUtils getInstance(Context mContext) {
if (instance == null) {
synchronized (ScreenSizeUtils.class) {
if (instance == null)
instance = new ScreenSizeUtils(mContext);
}
}
return instance;
}
private ScreenSizeUtils(Context mContext) {
WindowManager manager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics dm = new DisplayMetrics();
manager.getDefaultDisplay().getMetrics(dm);
screenWidth = dm.widthPixels;// 獲取螢幕解析度寬度
screenHeight = dm.heightPixels;// 獲取螢幕解析度高度
}
//獲取螢幕寬度
public int getScreenWidth() {
return screenWidth;
}
//獲取螢幕高度
public int getScreenHeight() {
return screenHeight;
}
}
我們現在可以自定義對話方塊了,那麼我們就來實現一個經常用到的一個底部選擇對話方塊,來看下效果圖吧:
- 先來碼這個對話方塊的佈局,
dialog_bottom.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="match_parent"
android:background="@android:color/transparent"
android:orientation="vertical">
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/round_corner"
android:text="拍照" />
<TextView
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:background="#ddd" />
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/round_corner"
android:text="相簿" />
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:background="@drawable/round_corner"
android:text="取消" />
<View
android:layout_width="match_parent"
android:layout_height="15dp" />
</LinearLayout>
- 接下來就可以為我們的對話方塊載入這個佈局了
Dialog dialog = new Dialog(this, R.style.NormalDialogStyle);
View view = View.inflate(this, R.layout.dialog_bottom, null);
dialog.setContentView(view);
dialog.setCanceledOnTouchOutside(true);
view.setMinimumHeight((int) (ScreenSizeUtils.getInstance(this).getScreenHeight() * 0.23f));
Window dialogWindow = dialog.getWindow();
WindowManager.LayoutParams lp = dialogWindow.getAttributes();
lp.width = (int) (ScreenSizeUtils.getInstance(this).getScreenWidth() * 0.9f);
lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
lp.gravity = Gravity.BOTTOM;
dialogWindow.setAttributes(lp);
dialog.show();
上面這一段帶程式碼的關鍵就是將Dialog放置在螢幕底部
lp.gravity = Gravity.BOTTOM;
並設定他的寬度為螢幕的90%lp.width = (int) (ScreenSizeUtils.getInstance(this).getScreenWidth() * 0.9f);
。相信大家之前都用的是popwindow來實現這個效果的,現在學會了這個是不是可以直接把他給替換了。哈哈……
七:圓形進度條對話方塊
1.這個就相對比較簡單了
ProgressDialog dialog = new ProgressDialog(this);
dialog.setMessage("正在載入中");
dialog.show();
2.當然我們也可以設定一個水平的進度條並顯示當前進度,只需要把他的樣式設定為ProgressDialog.STYLE_HORIZONTAL
即可。
final ProgressDialog dialog = new ProgressDialog(this);
dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
dialog.setMessage("正在載入中");
dialog.setMax(100);
final Timer timer = new Timer();
timer.schedule(new TimerTask() {
int progress = 0;
@Override
public void run() {
dialog.setProgress(progress += 5);
if (progress == 100) {
timer.cancel();
}
}
}, 0, 1000);
dialog.show();
八:BottomSheetDialog,一個可以上下拖動的對話方塊使用方法和Dialog還是差不多的。
BottomSheetDialog dialog = new BottomSheetDialog(this);
View view = getLayoutInflater().inflate(R.layout.activity_main, null);
dialog.setContentView(view);//設定顯示的內容,我這為了方便就直接把主佈局設定進去了。
dialog.show();
BottomSheetDialog會根據你設定的View大小來計算預設顯示出來的高度,內容越多顯示的越多反之則越少。當顯示的內容比較少的時候他預設顯示一點,這個時候就比較蛋疼了所以我們就要讓他一顯示就預設全部展開。
/**
* 預設展開對話方塊
*/
final FrameLayout frameLayout = (FrameLayout) dialog.findViewById(android.support.design.R.id.design_bottom_sheet);
frameLayout.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
//獲得BottomSheetBehavior
BottomSheetBehavior behavior = BottomSheetBehavior.from(frameLayout);
//設定對話方塊的的狀態
behavior.setState(BottomSheetBehavior.STATE_EXPANDED);
}
});
BottomSheetDialog
的操作基本上都是通過Behavior來設定的,所以關鍵就是獲得他的Behavior;
這裡還有小坑就是:當你向下滑動讓他消失的時候,對話方塊是看不見了但是他卻並沒有dismiss需要在點選一次螢幕才能完全消失。下面給出解決辦法:通過監聽他的狀態來手動dismiss();
behavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
@Override
public void onStateChanged(@NonNull View bottomSheet, int newState) {
if (newState == BottomSheetBehavior.STATE_HIDDEN)
dialog.dismiss();
}
@Override
public void onSlide(@NonNull View bottomSheet, float slideOffset) {
}
});