彈窗是圖形界面必備的一個模塊, 回憶一下windows那些噁心爆了的錯誤彈窗吧, 把彈窗製做的更高效友好一點是很是必要的. 這裏說兩個經常使用的彈窗類, PopupWindow和AlertDialog. 個人理解就是, PopupWindow較爲隨性, 能夠在任意位置彈窗, 好比你常常看到的朋友圈點讚的那個小的彈窗. 那AlertDialog就很正經了, 位置固定在中央, 好比無比煩人的更新提示就是用的它, 大多數都是消息標題+內容+肯定按鈕+取消按鈕. 好, 很少廢話了.html
官方文檔傳送門java
先來看一段常規的PopupWindow的使用, 而後逐行分析下.android
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);
複製代碼
解析:windows
- 首先確定是建立一個PopupWindow對象了, 固然, 它確定還有許多帶參數的構造方法, 而無參確定是最好理解的那種.
- 而後就是設置三連, 設置寬高, 設置佈局View. 若是想要顯示一個彈窗, 這三句話是必須的.
- 而後
popupWindow.setBackgroundDrawable(new ColorDrawable(0x00000000));
這個頗有意思. 在高版本的android中(好比8.0), 實測能夠不寫, 可是低版本就不行了(好比4.1), 低版本不寫的話, 會致使點擊返回或者是屏幕其它地方沒法取消彈窗, 因此穩妥起見仍是加上, 並設置一個透明色.popupWindow.setFocusable(true);
是比較重要的, 通常都爲true, 也就是彈窗以後, 焦點就到了彈窗, 你再點擊其它地方, 彈窗失去焦點就會消失.popupWindow.setOutsideTouchable(false);
這句在以前那句爲true的前提下, true和false效果幾乎同樣.- 再往下是添加一個動畫效果, 你能夠用默認的, 或者自定義.
- 最後一句顯示彈窗, 默認對齊左下, 後面兩個參數是偏移值, 應該很好理解啦. 而後咱們來看一張效果圖.
RelativeLayout rl_content = (RelativeLayout) findViewById(R.id.rl_content);
popupWindow.showAtLocation(rl_content, Gravity.CENTER, 0, 0);
複製代碼
補充:數組
- 顯示還有一種方法, showAtLocation(). 舉個栗子, 就是如上代碼, 先獲取一個佈局, 而後設置Gravity.CENTER, 以及偏移量, 這樣就會把彈窗設置到佈局中心加上偏移量的一個位置.
官方文檔傳送門bash
解析:app
- 先來看一下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);
ide
AlertDialog.Builder builder = new AlertDialog.Builder(this);
函數
- 好, 接下來進入正文. 咱們構建一個最簡單的彈窗. 固然, 如下代碼能夠濃縮成一行代碼, 可是不夠直觀, 我更喜歡清晰一點的代碼.
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();
複製代碼
- 注意一點就是,
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數組對應勾選
複製代碼
補充:佈局
- 咱們如今來講一個比較複雜的, 也比較有意思的. 就是在彈窗中填充自定義view. 固然啦, 還有adapter的方法, 可是我暫時不打算在此次的文章中寫, 由於用adapter的時候太多了, 可能要下次弄個單獨的部分.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp">
<EditText
android:id="@+id/et_account"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:ignore="TextFields" />
<EditText
android:id="@+id/et_password"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/et_account"
tools:ignore="TextFields" />
<Button
android:id="@+id/bt_cancel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_below="@id/et_password"
android:text="@string/bt_cancel"
tools:ignore="RtlHardcoded" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/et_password"
android:layout_toLeftOf="@id/bt_cancel"
android:text="@string/bt_login"
tools:ignore="RtlHardcoded" />
</RelativeLayout>
複製代碼
- 隨便寫個佈局文件, 而後咱們在java中加入以下一行. 要說的是, 你們仔細看效果圖, 會發現自定義View能夠和
builder.setMessage("message");
共存, 但事實上, 好像沒有這個必要, 我故意把一些非自定義的也展現出來, 其實自定義View徹底能夠所有本身寫.
builder.setView(View.inflate(this, R.layout.layout_login, null));
複製代碼
喜歡記得點個讚了, 有意見或者建議能夠評論區見哦, 固然啦, 暗中關注我也是能夠的.