AlertDialog入門與詳解(多種實現(xiàn)示例:自定義布局等)

廢話時間###

有一段時間沒好好敲代碼了序调,處理完手頭上一些瑣事,終于可以潛心修行余舶,就從這篇簡單而飽滿的技術文章開始我的簡書之旅吧啊鸭。
最近在不同項目做了一些不同的對話框,剛好來總結一下匿值。方便自己赠制,幫助他人。
本文由作者三汪首發(fā)于簡書千扔。

總覽###

1.什么是AlertDialog
2.AlertDialog入門以及基本使用(快速創(chuàng)建Dialog)
3.AlertDialog的進階(自定義布局憎妙、位置、大小曲楚、動畫厘唾、style)

1.什么是AlertDialog###

Google官方的開發(fā)文檔是這樣描述的:

A subclass of Dialog that can display one, two or three buttons. If you only want to display a String in this dialog box, use the setMessage() method. If you want to display a more complex view, look up the FrameLayout called "custom" and add your view to it:
FrameLayout fl = (FrameLayout) findViewById(android.R.id.custom); fl.addView(myView, new LayoutParams(MATCH_PARENT, WRAP_CONTENT));
The AlertDialog class takes care of automatically setting WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM for you based on whether any views in the dialog return true from View.onCheckIsTextEditor(). Generally you want this set for a Dialog without text editors, so that it will be placed on top of the current input method UI. You can modify this behavior by forcing the flag to your desired mode after calling onCreate(Bundle).

翻譯如下(手動翻譯的,可能不夠信達雅):

AlertDialog是Dialog的一個子類龙誊,可以顯示一到三個button抚垃。如果你只想在對話框中顯示一個字符串,使用serMessage()這個方法。如果你想要顯示更復雜的視圖鹤树,找到這個叫"custom"的幀布局并把你的視圖添加進去:
FrameLayout fl = (FrameLayout) findViewById(android.R.id.custom); fl.addView(myView, new LayoutParams(MATCH_PARENT, WRAP_CONTENT));
AlertDialog這個類根據(jù)是否有視圖從View.onCheckIsTextEditor()返回true來為你自動設置WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM通常你會想要為一個沒有文本編輯欄的對話框設置這個屬性铣焊,以便于該對話框被放置在當前輸入法界面的頂部。你可以在調(diào)用onCreate(Bundle)以后通過設置這個flag修改這一動作罕伯。

從官方文檔的描述中我們可以知道AlertDialog的這么幾個信息:

  • 直接繼承自Dialog
  • 可以有三個原生的button
  • 可以顯示文字也可以在原生的FrameLayout布局中添加自定義視圖

官方文檔沒有告訴我們的是:

  • 自定義布局可以不使用官方提供的FrameLayout
  • 可以自定義對話框出現(xiàn)和消失時的動畫
  • 可以設置對話框的大小曲伊、位置和style

下面我們來逐一說明。

2.快速創(chuàng)建你的Dialog###

代碼如下(可直接copy進你的項目使用):

        AlertDialog dialog = new AlertDialog.Builder(this).create();//創(chuàng)建對話框
        dialog.setIcon(R.mipmap.ic_launcher);//設置對話框icon
        dialog.setTitle("這是一個AlertDialog");//設置對話框標題
        dialog.setMessage("Hello world");//設置文字顯示內(nèi)容
        //分別設置三個button
        dialog.setButton(DialogInterface.BUTTON_POSITIVE,"確定", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                dialog.dismiss();//關閉對話框
            }
        });
        dialog.setButton(DialogInterface.BUTTON_NEUTRAL,"點我試試", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) { }
        });
        dialog.setButton(DialogInterface.BUTTON_NEGATIVE, "取消", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                dialog.dismiss();//關閉對話框
            }
        });
        dialog.show();//顯示對話框

效果圖


基礎對話框效果圖

Tips

  • AlertDialog的三個button對應DialogInterface中的三個常量追他,分別是:BUTTON_NEUTRAL,BUTTON_POSITIVE,BUTTON_NEGATIVE坟募。不同的常量所對應的button位置不同。其中邑狸,BUTTON_NEUTRAL在對話框左側懈糯,另外兩個在右側(不同版本的系統(tǒng)可能對應的位置不同,以實際情況為準)单雾。
  • AlertDialog dialog = new AlertDialog.Builder(this).create();的Builder()中傳入的context參數(shù)必須來自activity赚哗,而不能是application的,否則會報錯硅堆。
  • 當你什么都不設置的時候屿储,會彈出一個“白茫茫大地真干凈”的對話框。
  • 調(diào)用dismiss()方法可以關閉對話框硬萍。除了在button點擊事件中扩所,還可以用在CheckBox、RadioButton的onCheckedChanged事件中等朴乖,以實現(xiàn)在用戶完成選擇以后自動關閉對話框的功能。
  • setTitle助赞、setMessage买羞、setPositiveButton等這類設置動作還可以用builder對象來做,寫法不同雹食,效果一樣畜普。此處不再贅述。

3.簡單列表群叶、單選列表與復選列表對話框的實現(xiàn)示例###

簡單列表代碼如下:

        //初始化字符串數(shù)組
        final String[] strArray = new String[]{"床前明月光","意識地上霜","舉頭望明月","低頭思故鄉(xiāng)"};
        AlertDialog.Builder builder = new AlertDialog.Builder(this);//實例化builder
        builder.setIcon(R.mipmap.ic_launcher);//設置圖標
        builder.setTitle("簡單列表");//設置標題
        //設置列表
        builder.setItems(strArray, new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                Toast.makeText(MainActivity.this,strArray[which],Toast.LENGTH_SHORT).show();
            }
        });
        builder.create().show();//創(chuàng)建并顯示對話框

單選列表代碼如下:

        //初始化字符串數(shù)組
        final String[] strArray = new String[]{"離離原上草","一歲一枯榮","野火燒不盡","春風吹又生"};
        final AlertDialog.Builder builder = new AlertDialog.Builder(this);//實例化builder
        builder.setIcon(R.mipmap.ic_launcher);//設置圖標
        builder.setTitle("單選列表");//設置標題
        //設置單選列表
        builder.setSingleChoiceItems(strArray, 0, new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {

            }
        });
        //創(chuàng)建對話框
        AlertDialog dialog = builder.create();

        //設置確定按鈕
        dialog.setButton(DialogInterface.BUTTON_POSITIVE,"確定", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                dialog.dismiss();
            }
        });
        dialog.show();//顯示對話框

復選列表代碼如下:

  //初始化字符串數(shù)組
        final String[] strArray = new String[]{"白日依山盡","黃河入海流","欲窮千里目","更上一層樓"};
        final AlertDialog.Builder builder = new AlertDialog.Builder(this);//實例化builder
        builder.setIcon(R.mipmap.ic_launcher);//設置圖標
        builder.setTitle("多選列表");//設置標題
        //設置多選列表
        builder.setMultiChoiceItems(strArray, new boolean[]{false, false, false, false}, new DialogInterface.OnMultiChoiceClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which, boolean isChecked) {

            }
        });
        //創(chuàng)建對話框
        AlertDialog dialog = builder.create();
        //設置確定按鈕
        dialog.setButton(DialogInterface.BUTTON_POSITIVE,"確定", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                dialog.dismiss();
            }
        });
        dialog.show();//顯示對話框

效果圖:

簡單列表對話框效果圖
單選列表對話框效果圖
復選列表對話框效果圖

4.自定義布局對話框的簡單示例###

對于AlertDialog的自定義布局吃挑,官方提供了原生的FrameLayout(說明與使用方式參見前文開發(fā)文檔描述部分)供大家使用。但是街立,F(xiàn)rameLayout有時候并不能滿足大家的需求舶衬。因此,我們需要自己引入布局文件赎离。本文僅提供如何通過引入布局文件來實現(xiàn)自定義布局的示例逛犹。

代碼如下:

        //實例化布局
        View view = LayoutInflater.from(this).inflate(R.layout.item_custom,null);
        //找到并對自定義布局中的控件進行操作的示例
        EditText account = (EditText) view.findViewById(R.id.account);
        account.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
            }

            @Override
            public void afterTextChanged(Editable s) {
            }
        });
        //創(chuàng)建對話框
        AlertDialog dialog = new AlertDialog.Builder(this).create();
        dialog.setIcon(R.mipmap.ic_launcher);//設置圖標
        dialog.setTitle("自定義布局對話框");//設置標題
        dialog.setView(view);//添加布局
        //設置按鍵
        dialog.setButton(AlertDialog.BUTTON_POSITIVE, "登陸", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {

            }
        });
        dialog.setButton(AlertDialog.BUTTON_NEGATIVE, "取消", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {

            }
        });
        dialog.show();

效果圖:


自定義布局對話框效果圖

5.如何設置Dialog的位置、大小、動畫###

通過幾小段代碼來說明虽画,以供參考舞蔽。

代碼片段1:

        Window dialogWindow = dialog.getWindow();//獲取window對象
        dialogWindow.setGravity(Gravity.BOTTOM);//設置對話框位置
        dialogWindow.setLayout(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.WRAP_CONTENT);//設置橫向全屏
        dialogWindow.setWindowAnimations(R.style.share_animation);//設置動畫

styles.xml

     <style name="share_animation" parent="android:Animation">
        <item name="@android:windowEnterAnimation">@anim/dialog_enter</item>  //進入時的動畫
        <item name="@android:windowExitAnimation">@anim/dialog_exit</item>    //退出時的動畫
     </style>

dialog_enter.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    
    <translate
        android:fromYDelta="100%p"     <!--  %p指相對于父容器-->
        android:duration="600"                <!-- 持續(xù)時間-->
        />
</set>

dialog_exit.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    
    <translate
          android:toYDelta="100%p"
          android:duration="600"    
          />
</set>

代碼片段2:
(片段2與片段3轉載自:angeldevil)

        /*
         * 將對話框的大小按屏幕大小的百分比設置
         */
//        WindowManager m = getWindowManager();
//        Display d = m.getDefaultDisplay(); // 獲取屏幕寬、高用
//        WindowManager.LayoutParams p = dialogWindow.getAttributes(); // 獲取對話框當前的參數(shù)值
//        p.height = (int) (d.getHeight() * 0.6); // 高度設置為屏幕的0.6
//        p.width = (int) (d.getWidth() * 0.65); // 寬度設置為屏幕的0.65
//        dialogWindow.setAttributes(p);

代碼片段3:
(片段2與片段3轉載自:angeldevil)

        Window dialogWindow = dialog.getWindow();
        WindowManager.LayoutParams lp = dialogWindow.getAttributes();
        dialogWindow.setGravity(Gravity.LEFT | Gravity.TOP);

        /*
         * lp.x與lp.y表示相對于原始位置的偏移.
         * 當參數(shù)值包含Gravity.LEFT時,對話框出現(xiàn)在左邊,所以lp.x就表示相對左邊的偏移,負值忽略.
         * 當參數(shù)值包含Gravity.RIGHT時,對話框出現(xiàn)在右邊,所以lp.x就表示相對右邊的偏移,負值忽略.
         * 當參數(shù)值包含Gravity.TOP時,對話框出現(xiàn)在上邊,所以lp.y就表示相對上邊的偏移,負值忽略.
         * 當參數(shù)值包含Gravity.BOTTOM時,對話框出現(xiàn)在下邊,所以lp.y就表示相對下邊的偏移,負值忽略.
         * 當參數(shù)值包含Gravity.CENTER_HORIZONTAL時
         * ,對話框水平居中,所以lp.x就表示在水平居中的位置移動lp.x像素,正值向右移動,負值向左移動.
         * 當參數(shù)值包含Gravity.CENTER_VERTICAL時
         * ,對話框垂直居中,所以lp.y就表示在垂直居中的位置移動lp.y像素,正值向右移動,負值向左移動.
         * gravity的默認值為Gravity.CENTER,即Gravity.CENTER_HORIZONTAL |
         * Gravity.CENTER_VERTICAL.
         * 
         * 本來setGravity的參數(shù)值為Gravity.LEFT | Gravity.TOP時對話框應出現(xiàn)在程序的左上角,但在
         * 我手機上測試時發(fā)現(xiàn)距左邊與上邊都有一小段距離,而且垂直坐標把程序標題欄也計算在內(nèi)了,
         * Gravity.LEFT, Gravity.TOP, Gravity.BOTTOM與Gravity.RIGHT都是如此,據(jù)邊界有一小段距離
         */
        lp.x = 100; // 新位置X坐標
        lp.y = 100; // 新位置Y坐標
        lp.width = 300; // 寬度
        lp.height = 300; // 高度
        lp.alpha = 0.7f; // 透明度

        // 當Window的Attributes改變時系統(tǒng)會調(diào)用此函數(shù),可以直接調(diào)用以應用上面對窗口參數(shù)的更改,也可以用setAttributes
        // dialog.onWindowAttributesChanged(lp);
        dialogWindow.setAttributes(lp);

以上码撰。
歡迎留言探討渗柿,指正。
希望我總結的東西能夠對你有所幫助脖岛。

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末做祝,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子鸡岗,更是在濱河造成了極大的恐慌混槐,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,544評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件轩性,死亡現(xiàn)場離奇詭異声登,居然都是意外死亡,警方通過查閱死者的電腦和手機揣苏,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,430評論 3 392
  • 文/潘曉璐 我一進店門悯嗓,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人卸察,你說我怎么就攤上這事脯厨。” “怎么了坑质?”我有些...
    開封第一講書人閱讀 162,764評論 0 353
  • 文/不壞的土叔 我叫張陵合武,是天一觀的道長。 經(jīng)常有香客問我涡扼,道長稼跳,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,193評論 1 292
  • 正文 為了忘掉前任吃沪,我火速辦了婚禮汤善,結果婚禮上,老公的妹妹穿的比我還像新娘票彪。我一直安慰自己红淡,他們只是感情好,可當我...
    茶點故事閱讀 67,216評論 6 388
  • 文/花漫 我一把揭開白布降铸。 她就那樣靜靜地躺著在旱,像睡著了一般。 火紅的嫁衣襯著肌膚如雪垮耳。 梳的紋絲不亂的頭發(fā)上颈渊,一...
    開封第一講書人閱讀 51,182評論 1 299
  • 那天遂黍,我揣著相機與錄音,去河邊找鬼俊嗽。 笑死雾家,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的绍豁。 我是一名探鬼主播芯咧,決...
    沈念sama閱讀 40,063評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼竹揍!你這毒婦竟也來了敬飒?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 38,917評論 0 274
  • 序言:老撾萬榮一對情侶失蹤芬位,失蹤者是張志新(化名)和其女友劉穎无拗,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體昧碉,經(jīng)...
    沈念sama閱讀 45,329評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡英染,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,543評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了被饿。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片四康。...
    茶點故事閱讀 39,722評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖狭握,靈堂內(nèi)的尸體忽然破棺而出闪金,到底是詐尸還是另有隱情,我是刑警寧澤论颅,帶...
    沈念sama閱讀 35,425評論 5 343
  • 正文 年R本政府宣布哎垦,位于F島的核電站,受9級特大地震影響嗅辣,放射性物質(zhì)發(fā)生泄漏撼泛。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,019評論 3 326
  • 文/蒙蒙 一澡谭、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧损俭,春花似錦蛙奖、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,671評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至琐脏,卻和暖如春攒砖,著一層夾襖步出監(jiān)牢的瞬間缸兔,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,825評論 1 269
  • 我被黑心中介騙來泰國打工吹艇, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留惰蜜,地道東北人。 一個月前我還...
    沈念sama閱讀 47,729評論 2 368
  • 正文 我出身青樓受神,卻偏偏與公主長得像抛猖,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子鼻听,可洞房花燭夜當晚...
    茶點故事閱讀 44,614評論 2 353

推薦閱讀更多精彩內(nèi)容

  • ¥開啟¥ 【iAPP實現(xiàn)進入界面執(zhí)行逐一顯】 〖2017-08-25 15:22:14〗 《//首先開一個線程财著,因...
    小菜c閱讀 6,401評論 0 17
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,077評論 25 707
  • Day1: 在代碼中通過R.string.hello_world可以獲得該字符串的引用; 在XML中通過@stri...
    冰凝雪國閱讀 1,400評論 0 5
  • 不是優(yōu)種葡萄的老葡萄樹撑碴,葡萄架交錯的藤蔓撑教,竟然得早早為它準備許多架桿。形成一個過廊醉拓。北方干燥的院子里伟姐,竟然生出一...
    咫尺為鄰閱讀 463評論 2 0
  • 2015年11月22日23:25:15 丁亥年玫镐,壬寅日,小雪至怠噪。 我一直特別喜歡這句話恐似,一讀它,腦海里便會出現(xiàn)一些...
    邡素閱讀 386評論 0 0