1. 程式人生 > >Android 對話方塊相關總結

Android 對話方塊相關總結

常用的對話方塊相關的有:AlertDialog,ProgressDialog,自定義的對話方塊(自定義的對話方塊的長寬設定需要注意),還有任意位置在其他應用上都可以彈出的對話方塊。其中任意位置在其他應用上都可以彈出的對話方塊見另一篇博文:點選跳轉。該博文的demo放在gihub上:點選跳轉。只有“將事件傳遞迴對話方塊的宿主”的例子在module:”passEventToHost”裡,其他都在dialog裡。

1.純粹的 AlertDialog以及設定位置

AlertDialog對話方塊是非常常用的對話方塊,一般又一個頭部,中間的說明文字和下面的按鈕組成。按鈕的數量可以是:1、2或3。注意的是,下面按鈕中,最前面到的那個按鈕,在Android的不同版本中,位置是不同的。
下面給出程式碼:

 AlertDialog.Builder dialog = new AlertDialog.
                Builder(MainActivity.this);
        dialog.setTitle("對話方塊最上面的字");//對話方塊最上面的字
        dialog.setMessage("對話方塊中部的字");//對話方塊中部的字
        dialog.setCancelable(false);//如果是false,點選其他位置或者返回鍵無效,這個地方預設為true
//以下為對話方塊最下面的選擇項
        dialog.setPositiveButton("右邊"
, new DialogInterface. OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { Toast.makeText(MainActivity.this, "右邊", Toast.LENGTH_SHORT).show(); } }); //需要第二個按鈕才新增如下的setNegativeButton()
dialog.setNegativeButton("左邊", new DialogInterface. OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { Toast.makeText(MainActivity.this, "左邊", Toast.LENGTH_SHORT).show(); } }); //需要第三個按鈕時,才新增如下的setNeutralButton(),android老版本是在中間,比如4.0,在新版本是在前面,沒有研究從哪個版本開始變的 dialog.setNeutralButton("前面", new DialogInterface. OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { Toast.makeText(MainActivity.this, "前面", Toast.LENGTH_SHORT).show(); dialog.dismiss(); } }); dialog.show();

在Android 8.0 模擬器上執行效果:

這裡寫圖片描述

2. ProgressDialog和自定義對話方塊

雖然,ProgressDialog官方在Androidd 8.0中已經棄用它了:“This class was deprecated in API level 26.“,但是實際用Android 8.0模擬器執行並沒有出現問題。而且官網沒有給出效果相同的直接代替的類。只是建議用別的東西代替,如ProgressBar。
下面給出程式碼:

ProgressDialog progressDialog = new ProgressDialog
                (MainActivity.this);
        progressDialog.setTitle("對話方塊上部的字");
        progressDialog.setMessage("正在載入.....");
        progressDialog.setCancelable(true);//如果是false,點選其他位置或者返回鍵無效,預設為true
        progressDialog.show();
        //progressDialog.dismiss();//此句讓progressDialog消失

在Android 8.0 模擬器上執行效果:
這裡寫圖片描述
自定義對話方塊
下面給出一個簡單的,避開棄用progressDialog問題的方法:自定義對話方塊。通過getInflater.inflate(R.layout.dialog_layout, null)獲取View;通過builder.setView()給對話方塊設定view。這樣設定的Dialog寬度始終會如右圖下圖所示,而高度是wrap_content且有一個最小值,不會比那個值小,在
佈局檔案dialog_layout.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="wrap_content"
    android:orientation="vertical">
    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="20dp"
        android:layout_marginStart="20dp"
        android:layout_marginTop="15dp"
        android:orientation="horizontal">
        <ProgressBar

            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
        <TextView
            android:id="@+id/message"
            android:layout_marginLeft="20dp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical"
            android:text="message"
            android:textSize="17sp"/>
    </LinearLayout>
</LinearLayout>

java程式碼如下,通過message.setText()改變下方顯示文字, builder.setTitle()設定上方顯示文字。

 AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
        LayoutInflater inflater = getLayoutInflater();
        View dialogView = inflater.inflate(R.layout.dialog_layout, null);
        builder.setView(dialogView).create();
        builder.setTitle("進度");
        TextView message = dialogView.findViewById(R.id.message);
        message.setText("進度:%10");
        builder.show();

下面對比一下,效果基本與ProgressDialog一致:

這裡寫圖片描述

3. 自定義對話方塊(考慮wrap_content時的大小問題)

自定義對話方塊,就是自己寫一個佈局,讓對話方塊載入佈局,並且能監聽這個佈局裡面的點選事件,並且對話方塊可以響應點選消失。需要注意的是,有時候自定義的根佈局高和寬是wrap_content,這時定義的對話方塊長寬會失效,下面是考慮到這種問題的自定義對話方塊。但是比較麻煩,如果根佈局大小可以寫死,就不需要考慮這個問題
首先寫一個對話方塊的佈局:my_dialog.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:background="@color/colorAccent"
              android:orientation="vertical">

    <TextView
        android:layout_width="300dp"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:text="自定義對話方塊"
        android:textSize="20sp"/>

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:layout_marginTop="20dp">

        <Button
            android:id="@+id/leftBt"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="左按鈕"/>

        <Button
            android:id="@+id/rightBt"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="右按鈕"/>
    </LinearLayout>

</LinearLayout>

設計對話方塊的style,目的是去控制對話方塊長寬,並且避免出現一些上部陰影,下面是新增在styles.xml中的程式碼,其中windowIsFloating讓java程式碼部分控制大小生效,windowNoTitle避免出現一些上部陰影:

<style name="style_dialog" parent="android:style/Theme.Dialog">
        <item name="android:windowNoTitle">true</item>
        <item name="android:windowIsFloating">true</item>
    </style>

在java程式碼部分會用到上面的檔案,注意一點:匯入的AlertDialog語句是:import android.support.v7.app.AlertDialog;(不要匯入錯誤成另一個)

 //獲取自定義佈局view例項
        View layout = LayoutInflater.from(this).inflate(R.layout.my_dialog, null);
        //在對話方塊里加載佈局:setView()方法
        final AlertDialog.Builder dialog = new AlertDialog.
                Builder(MainActivity.this,R.style.style_dialog);
        dialog.setCancelable(false)//如果是false,點選其他位置或者返回鍵無效,這個地方預設為true
                .setView(layout);//這裡載入佈局
        final AlertDialog alert = dialog.create();

        //設定對話方塊的寬和高(注意,設定長寬還需要設定R.style.style_dialog,否則會出現很多問題),
        //並且如果需要設定佈局大小,而不是wrap_content,那麼需要在佈局的子項裡面設定大小,
        //直接在最外層設定是無效的
        Window window = alert.getWindow();
        window.getDecorView().setPadding(0, 0, 0, 0);//void setPadding (int left, int top,int right,int bottom)
        WindowManager.LayoutParams lp = window.getAttributes();
        lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
        lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
        window.setAttributes(lp);
        window.setGravity(Gravity.CENTER);//對話框出現的位置

        //按鈕監聽事件
        Button btLeft, btRight;
        btLeft = layout.findViewById(R.id.leftBt);
        btRight = layout.findViewById(R.id.rightBt);
        btLeft.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //這裡寫左按鈕點選響應事件
                Toast.makeText(MainActivity.this, "左按鈕", Toast.LENGTH_SHORT).show();
                alert.dismiss();//讓對話方塊消失
            }
        });

        btRight.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //這裡寫右按鈕點選響應事件
                Toast.makeText(MainActivity.this, "右按鈕", Toast.LENGTH_SHORT).show();
                alert.dismiss();//讓對話方塊消失
            }
        });
        alert.show();
    }

在擬器上執行效果:
這裡寫圖片描述

4.單選列表對話方塊

新增builder.setItems()即可,setItems第一個引數是顯示資料的陣列,第二個是點選監聽DialogInterface.OnClickListener物件。也可以使用 setAdapter() 指定一個列表。 這樣一來,您就可以使用 ListAdapter 以動態資料(如來自資料庫的資料)支援列表。

 String[] arr={"第一項","第二項","第三項"};
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setTitle("單選列表對話方塊")
                .setItems(arr, new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int which) {
                        // which是點選列表位置
                        Toast.makeText(MainActivity.this, which+"", Toast.LENGTH_SHORT).show();
                    }
                });
         builder.create().show();
    }

效果是這樣的:
這裡寫圖片描述

5.多選列表對話方塊

需要定義一個List物件儲存選定內容,在點選確定時讀取。依靠setMultiChoiceItems()方法實現多選列表對話方塊。

List <String>mSelectedItems;//用於多選列表對話方塊選擇項的暫時儲存


String[] arr={"第一項","第二項","第三項"};
        mSelectedItems = new ArrayList();  //用來存放被選中的項
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        // Set the dialog title
        builder.setTitle("多選列表對話方塊")
                // Specify the list array, the items to be selected by default (null for none),
                // and the listener through which to receive callbacks when items are selected
                .setMultiChoiceItems(arr, null,
                        new DialogInterface.OnMultiChoiceClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which,
                                                boolean isChecked) {
                                if (isChecked) {
                                    // 如果選擇一項,那麼在選定的項中新增此項
                                    mSelectedItems.add(which+"");
                                } else if (mSelectedItems.contains(which)) {
                                    // 如果取消選擇,那麼在選定的項中移除此項
                                    mSelectedItems.remove(Integer.valueOf(which));
                                }
                            }
                        })
                // Set the action buttons
                .setPositiveButton("OK", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int id) {
                        //確定
                        String result="";
                        for(String str:mSelectedItems){
                            result+=str;
                        }
                        //這裡輸出被選中項
                        Toast.makeText(MainActivity.this, result, Toast.LENGTH_SHORT).show();
                    }
                })
                .setNegativeButton("cancel", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int id) {
                        //取消
                    }
                });

         builder.create().show();

效果如下:
這裡寫圖片描述

6.全屏的對話方塊

1.狀態列消失,螢幕全部佔滿的對話方塊

建議使用Dialog而不是AlertDialog,因為AlertDialog自帶的一些屬性使全屏變得比Dialog麻煩一些。Dialog與AlertDialog程式碼上的區別,主要是它沒有Builder,而是直接在Dialog上對對話方塊屬性進行設定。而要讓Dialog全屏是非常簡單的,只需要在例項化Dialog物件時像這樣傳遞引數即可。注意,這樣的話,螢幕上方狀態列也會消失,對話方塊佔據整個螢幕(除虛按鍵)。

Dialog dialog = new Dialog(this,android.R.style.
Theme_Light_NoTitleBar_Fullscreen);

完整的一個自定義佈局的全屏對話方塊程式碼:

public showDialog(Activity activity){
Dialog dialog = new Dialog(activity,
android.R.style.Theme_Light_NoTitleBar_Fullscreen);//第二引數為關鍵程式碼
        View view = LayoutInflater.from(activity).
        inflate(R.layout.diag_list, null, false);//diag_list是對話方塊的佈局檔案
        dialog.setContentView(view);
        //這裡區別於AlertDialog,Builder的setView(View)

        dialog.show();
}

下面在提供一種狀態列不消失的全屏對話方塊的方法:

2.讓狀態列顯示的全屏對話方塊

需要設定對話方塊長寬都是match_parent,因為預設是wrap_content

dialog.getWindow().setLayout(WindowManager.LayoutParams.MATCH_PARENT, WindowManager
                .LayoutParams.MATCH_PARENT);

需要設定Dialog的背景,因為它預設背景會距離螢幕上下左右各8dp

dialog.getWindow().setBackgroundDrawable(null);
//注意,以上寫法會使dialog背景透明,可以在對話方塊佈局檔案中設定佈局背景色。
//或像下面一樣,設背景色為白色
//dialog.getWindow().setBackgroundDrawable(new 
//ColorDrawable(getResources().getColor(android.R.color.white)));

以上兩步可以使Dialog全屏(不包含狀態列),下面一個完整例子:


 public void showDialog(Activity activity) {
        Dialog dialog = new Dialog(activity);//一個引數
        View view = LayoutInflater.from(activity).inflate(R.layout.diag_list, null, false);
        dialog.setContentView(view);

        dialog.getWindow().setLayout(WindowManager.LayoutParams.MATCH_PARENT, WindowManager
                .LayoutParams.MATCH_PARENT);
        dialog.getWindow().setBackgroundDrawable(new ColorDrawable(activity.getResources().getColor(android.R.color.white)));
        dialog.show();

    }