Android彈窗二則: PopupWindow和AlertDialog

前言

彈窗是圖形界面必備的一個模塊, 回憶一下windows那些噁心爆了的錯誤彈窗吧, 把彈窗製作的更高效友好一點是非常必要的. 這裡說兩個常用的彈窗類, PopupWindow和AlertDialog.

Android彈窗二則: PopupWindow和AlertDialog

為了保護你的眼睛, 圖片已處理


PopupWindow

  • 實例解析

先來看一段常規的PopupWindow的使用, 然後逐行分析下.

PopupWindow popupWindow = new PopupWindow();popupWindow.setWidth(ViewGroup.LayoutParams.WRAP_CONTENT);popupWindow.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT);popupWindow.setContentView(View.inflate(this, R.layout.layout_popup, null));popupWindow.setBackgroundDrawable(new ColorDrawable(0x00000000));popupWindow.setFocusable(true);popupWindow.setOutsideTouchable(false);popupWindow.setAnimationStyle(R.style.anim_menu_bottombar);popupWindow.showAsDropDown(bt_popup, 0, 0);

解析:

  • 首先肯定是創建一個PopupWindow對象了, 當然, 它肯定還有許多帶參數的構造方法, 而無參肯定是最好理解的那種.

  • 然後就是設置三連, 設置寬高, 設置佈局View. 如果想要顯示一個彈窗, 這三句話是必須的.

  • 然後popupWindow.setBackgroundDrawable(new ColorDrawable(0x00000000));這個很有意思. 在高版本的android中(比如8.0), 實測可以不寫, 但是低版本就不行了(比如4.1), 低版本不寫的話, 會導致點擊返回或者是屏幕其它地方無法取消彈窗, 所以穩妥起見還是加上, 並設置一個透明色.

  • popupWindow.setFocusable(true);是比較重要的, 一般都為true, 也就是彈窗之後, 焦點就到了彈窗, 你再點擊其它地方, 彈窗失去焦點就會消失. popupWindow.setOutsideTouchable(false);這句在之前那句為true的前提下, true和false效果幾乎一樣.

  • 再往下是添加一個動畫效果, 你可以用默認的, 或者自定義.

  • 最後一句顯示彈窗, 默認對齊左下, 後面兩個參數是偏移值, 應該很好理解啦. 然後我們來看一張效果圖.

Android彈窗二則: PopupWindow和AlertDialog

效果圖


  • 內容補充

RelativeLayout rl_content = (RelativeLayout) findViewById(R.id.rl_content);popupWindow.showAtLocation(rl_content, Gravity.CENTER, 0, 0);

補充:

  • 顯示還有一種方法, showAtLocation(). 舉個栗子, 就是如上代碼, 先獲取一個佈局, 然後設置Gravity.CENTER, 以及偏移量, 這樣就會把彈窗設置到佈局中心加上偏移量的一個位置.


AlertDialog

  • 實例解析

解析:

  • 先來看一下Module中的build.gradle, 關鍵是compile 'com.android.support:appcompat-v7:25.3.1', 版本要確保大於22, 因為22中引入了Material Design風格的Dialog(5.0引入的Material Design), 當然, 如果你用Android Studio, 這點基本無需擔心.

dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { exclude group: 'com.android.support', module: 'support-annotations' }) compile 'com.android.support:appcompat-v7:25.3.1' compile 'com.android.support.constraint:constraint-layout:1.0.2' testCompile 'junit:junit:4.12'}
  • 再者下面兩句是不同的, 第二種實例化方法會導致5.0前和5.0後風格不統一, 這裡來兩張效果圖. 用API16的虛擬機.

android.support.v7.app.AlertDialog.Builder builder = new android.support.v7.app.AlertDialog.Builder(this);

AlertDialog.Builder builder = new AlertDialog.Builder(this);

Android彈窗二則: PopupWindow和AlertDialog

右側是Material Design風格

  • 好, 接下來進入正文. 我們構建一個最簡單的彈窗. 當然, 以下代碼可以濃縮成一行代碼, 但是不夠直觀, 我更喜歡清晰一點的代碼.

android.support.v7.app.AlertDialog.Builder builder = new android.support.v7.app.AlertDialog.Builder(this);builder.setIcon(R.mipmap.ic_launcher);builder.setTitle("title");builder.setMessage("message");builder.setPositiveButton("positive", null);builder.setNegativeButton("negative", null);builder.setNeutralButton("neutral", null);builder.setCancelable(true);android.support.v7.app.AlertDialog dialog = builder.create();dialog.show();

Android彈窗二則: PopupWindow和AlertDialog

舉個栗子

  • 注意一點就是, setPositiveButton等函數第二個參數其實是監聽器, 你可以如下操作.

builder.setPositiveButton("positive", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialogInterface, int i) { Toast.makeText(getApplicationContext(), "positive", Toast.LENGTH_SHORT).show(); }});
  • 這行builder.setCancelable(true);就是意思點擊彈窗以外的部分可以取消彈窗, 設置false則不取消彈窗, 按需設置啦.

  • 然後就是AlertDialog是非常便於放入各種條目的, 比如單選和多選. 但是注意, 這之間會起衝突, 比如之前的builder.setMessage("message");和設置單選多選條目不能同時存在. 下方展示代碼和效果圖. 當然了, 監聽我都沒寫, 按需求自己完成啦.

builder.setItems(new String[]{"1", "2", "3"}, null);
builder.setSingleChoiceItems(new String[]{"1", "2", "3"}, 2, null); //數字對應默認選中, 從0開始
builder.setMultiChoiceItems(new String[]{"1", "2", "3"}, new boolean[]{true, true, false}, null); //boolean數組對應勾選

Android彈窗二則: PopupWindow和AlertDialog

普通條目展示

Android彈窗二則: PopupWindow和AlertDialog

單選多選條目展示


  • 內容補充

補充:

  • 我們現在來說一個比較複雜的, 也比較有意思的. 就是在彈窗中填充自定義view. 當然啦, 還有adapter的方法, 但是我暫時不打算在這次的文章中寫, 因為用adapter的時候太多了, 可能要下次弄個單獨的部分.

Android彈窗二則: PopupWindow和AlertDialog

舉個栗子

   
  • 隨便寫個佈局文件, 然後我們在java中加入如下一行. 要說的是, 大家仔細看效果圖, 會發現自定義View可以和builder.setMessage("message");共存, 但事實上, 好像沒有這個必要, 我故意把一些非自定義的也展示出來, 其實自定義View完全可以全部自己寫.

builder.setView(View.inflate(this, R.layout.layout_login, null));

最後


分享到:


相關文章: