AlertDialog和Popupwindow的區別:
1)AlertDialog是非阻塞線程的,Popupwindow是阻塞線程的。
2)Dialog沒法設置寬為整個屏幕寬,總有點邊界。Popupwindow可以。
1、Dialog及設置Dialog的動畫
設置Dialog的位置和大小與加載的布局文件無關。需自己設置dialog參數。
1)設置Dialog位置:
設置位置時必須先指定Dialog的gravity屬性,否則指定大小無用。
/*
* lp.x與lp.y表示相對于原始位置的偏移.
* 當參數值包含Gravity.LEFT時,對話框出現在左邊,所以lp.x就表示相對左邊的偏移,負值忽略.
* 當參數值包含Gravity.RIGHT時,對話框出現在右邊,所以lp.x就表示相對右邊的偏移,負值忽略.
* 當參數值包含Gravity.TOP時,對話框出現在上邊,所以lp.y就表示相對上邊的偏移,負值忽略.
* 當參數值包含Gravity.BOTTOM時,對話框出現在下邊,所以lp.y就表示相對下邊的偏移,負值忽略.
* 當參數值包含Gravity.CENTER_HORIZONTAL時
* ,對話框水平居中,所以lp.x就表示在水平居中的位置移動lp.x像素,正值向右移動,負值向左移動.
* 當參數值包含Gravity.CENTER_VERTICAL時
* ,對話框垂直居中,所以lp.y就表示在垂直居中的位置移動lp.y像素,正值向右移動,負值向左移動.
* gravity的默認值為Gravity.CENTER,即Gravity.CENTER_HORIZONTAL |
* Gravity.CENTER_VERTICAL.
*
* 本來setGravity的參數值為Gravity.LEFT | Gravity.TOP時對話框應出現在程序的左上角,但在
* 我手機上測試時發現距左邊與上邊都有一小段距離,而且垂直坐標把程序標題欄也計算在內了,
* Gravity.LEFT, Gravity.TOP, Gravity.BOTTOM與Gravity.RIGHT都是如此,據邊界有一小段距離
*/
lp.y=90;
2)去標題:
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
3)設置Dialog的寬和高
WindowManager wm = getWindowManager();
Display display = wm.getDefaultDisplay();
android.view.WindowManager.LayoutParams lp = dialog.getWindow().getAttributes();
lp.width = display.getWidth();
lp.height =LayoutParams.WRAP_CONTENT;
dialog.getWindow().setAttributes(lp);
4)設置動畫
設置Dialog的動畫只能通過設置xml的形式,然后設置在style中,最后在代碼中設置。
2)貼代碼
第一步:寫動畫xml
window_in.xml:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >
<translate
android:duration="500"
android:fromXDelta="0"
android:fromYDelta="1000"
android:toXDelta="0"
android:toYDelta="0" />
</set>
window_out.xml:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >
<translate
android:duration="500"
android:fromXDelta="0"
android:fromYDelta="0"
android:toXDelta="0"
android:toYDelta="1000" />
</set>
第二步:動畫配置到style中
<style name="main_menu_animstyle">
<item name="android:windowEnterAnimation">@anim/settingswindow_in_anim</item>
<item name="android:windowExitAnimation">@anim/settingswindow_out_anim</item>
</style>
第三步:將動畫用于dialog中
Window window = dialog.getWindow();
//設置顯示動畫
window.setWindowAnimations(R.style.main_menu_animstyle);
WindowManager.LayoutParams wl = window.getAttributes();
wl.x = 0;
wl.y = getWindowManager().getDefaultDisplay().getHeight();
//設置顯示位置
dialog.onWindowAttributesChanged(wl);//設置點擊外圍解散
dialog.setCanceledOnTouchOutside(true);
dialog.show();
2、Popupwindow
1)設置顯示位置特別方便:
showAsDropDown(View anchor):相對某個控件的位置(正左下方),無偏移。
showAsDropDown(View anchor, int xoff, int yoff):相對某個控件的位置,有偏移。
showAtLocation(View parent, int gravity, int x, int y):相對于父控件的位置(例如正中央Gravity.CENTER,下方Gravity.BOTTOM等),可以設置偏移或無偏移。
2)點擊Popupwindow以外區域自動消失
注意一定要設置backgroundDrawable
//參數也可以是下面這倆值
//1、getResources().getDrawable(R.drawable.abc)
//2、getWallpaper()
//當你發現有背景色時,需給布局文件設置背景色,這樣即可覆蓋系統自帶的背景色。
pw.setBackgroundDrawable(new BitmapDrawable());
pw.setOutsideTouchable(true);
有種說法是pw.setFocusable(false);,則不點擊區域以外不會消失。經測試,此種說法不對。
3)完整用法貼代碼:
View view=LayoutInflater.from(MainActivity.this).inflate(R.layout.popup, null);
PopupWindow pw=new PopupWindow(view, ViewGroup.LayoutParams.MATCH_PARENT,300);
// pw.setFocusable(true);------完全沒用啊
//參數也可以是下面這倆值
//1、getResources().getDrawable(R.drawable.abc)
//2、getWallpaper()
//當你發現有背景色時,需給布局文件設置背景色,這樣即可覆蓋系統自帶的背景色。
pw.setBackgroundDrawable(new BitmapDrawable());
pw.setOutsideTouchable(true);
pw.showAsDropDown(findViewById(R.id.btn), 0,50);
//pw.showAtLocation(findViewById(R.id.btn), Gravity.BOTTOM, 0, 0);
PopupWindow
顧名思義為彈出式菜單,
不同于Dialag對話框,PopupWindow
不會使宿主activity組件失去焦點,
也就是說PopupWindow彈出后,
你可以與宿主activity進行交互,
Dialog卻不能做到這一點。
注意:PopupWindow組件的使用問題,PopupWindow是一個阻塞對話框,如果你直接在Activity創建的方法中顯示它,則會報錯:android.view.WindowManager$BadTokenException:Unable to add window -- token null is not valid; is your activity running?
總結: PopupWindow必須在某個事件中顯示或者是開啟一個新線程去調用,不能直接在onCreate方法中顯示一個Popupwindow,否則永遠會有以上的錯誤。
總結一下:
(1)Popupwindow在顯示之前一定要設置寬高,Dialog無此限制。
(2)Popupwindow默認不會響應物理鍵盤的back,除非顯示設置了popup.setFocusable(true);而在點擊back的時候,Dialog會消失。
(3)Popupwindow不會給頁面其他的部分添加蒙層,而Dialog會。
(4)Popupwindow沒有標題,Dialog默認有標題,可以通過dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);取消標題
(5)Popupwindow.showAtLocation(parent,Gravity.NO_GRAVITY, x, y);如果x=y=0那么會顯示在屏幕的最左上角,覆蓋在狀態欄上。Dialog設置params.x = params.y = 0是從標題欄開始顯示,不會覆蓋在狀態欄上。
(6)在一個頁面上,可以同時顯示多個Popupwindow,也可以同時顯示多個Dialog,最后出現的那個占有焦點。
(7)二者顯示的時候都要設置Gravity。如果不設置,Dialog默認是Gravity.CENTER。
(8)二者都有默認的背景,都可以通過setBackgroundDrawable(new ColorDrawable(android.R.color.transparent));去掉。