天天看點

AlertDialog按鍵後不取消對話框實作方式AlertDialog按鍵後不取消對話框實作方式

AlertDialog按鍵後不取消對話框實作方式

我們在使用預設Android對話框的上的按鍵時,當我們按下後,對話框就會自動關閉,但有時某些需求需要我們通過對話框進行與界面進行互動,而不是立即關閉,我們如何實作呢?先看下圖吧!
AlertDialog按鍵後不取消對話框實作方式AlertDialog按鍵後不取消對話框實作方式
如圖Dialog使用了DatePicker和TimePicker,将按鍵設定日期和時間(2016年9月9日 上午 9點09),這裡我設定完日期後還需要提供設定時間,如果把日期和時間弄到一個界面效果不太理想,于是我們通過Dialog上按鈕進行切換

實作方法

AlertDialog提供三種positive按鈕、negative按鈕以及neutral按鈕
  1. 通過反射将Dialog類中的私有布爾類型成員“mShowing”修改為false
    private void canNotCloseDialog(DialogInterface dialogInterface) {
        try {
            Class<? extends DialogInterface> aClass = dialogInterface.getClass();
            Class<?> superclass = aClass.getSuperclass().getSuperclass();
            Field field = superclass.getDeclaredField("mShowing");
            field.setAccessible(true);
            field.set(dialogInterface, false);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
               
  2. (推薦)通過alertDialog.getButton()方法,拿到按鍵對象,設定按鍵偵聽
    Button btNegative = alertDialog.getButton(AlertDialog.BUTTON_NEGATIVE);
    btNegative.setOnClickListener(new View.OnClickListener() {
        ...
    }
               

分析

這裡還存在以下幾個問題:
1. 這兩種方法有什麼差別?為什麼推薦第二種?
2. 應該在什麼時間使用?
           
  1. 問題1:這兩種方法有什麼差別?為什麼推薦第二種?
    1. 首先方法1的核心是修改Dialog類中的私有布爾類型成員“mShowing”,谷歌并不提供這個修改該變量的方法,是以有可能在未來谷歌更新過程中,導緻反射修改失效。
    2. 方法1修改後,所有按鍵(positive按鈕、negative按鈕以及neutral按鈕)點選後均無法關閉對話框,不夠靈活。
    3. 方法2解決了以上兩個問題是以推薦
  2. 問題2:應該在什麼時間使用?
    兩種方法均隻能在dialog顯示後才能生效
    //在dialog顯示偵聽進行設定
    alertDialog.setOnShowListener(new DialogInterface.OnShowListener() {
        @Override
        public void onShow(DialogInterface dialog) {
            //在這裡處理按鍵不取消
            ...
        }
    }
               

代碼

理論說完附上上圖的關鍵代碼

dialog_date_picker.xml

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
>

<DatePicker
    android:id="@+id/dp_dialog"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    >

</DatePicker>

<TimePicker
    android:id="@+id/tp_dialog"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:visibility="invisible"
    />
</FrameLayout>
           

dialog關鍵代碼

Date date = new Date();
View view = View.inflate(getActivity(), R.layout.dialog_date_picker, null);
final DatePicker datePicker = (DatePicker) view.findViewById(R.id.dp_dialog);
final TimePicker timePicker = (TimePicker) view.findViewById(R.id.tp_dialog);

Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH);
int day = calendar.get(Calendar.DAY_OF_MONTH);
int hour = calendar.get(Calendar.HOUR_OF_DAY);
int minute = calendar.get(Calendar.MINUTE);

timePicker.setHour(hour);
timePicker.setMinute(minute);
datePicker.init(year, month, day, null);

final AlertDialog alertDialog = new AlertDialog.Builder(getActivity())
        .setTitle(R.string.date_picker_title)
        .setView(view)
        .setNegativeButton(R.string.dialog_to_time, null)
        .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    int year = datePicker.getYear();
                    int month = datePicker.getMonth();
                    int day = datePicker.getDayOfMonth();
                    int hour = timePicker.getHour();
                    int minute = timePicker.getMinute();
                    Date date = new GregorianCalendar(year,
                            month,
                            day,
                            hour,
                            minute).getTime();
                    sendResult(date);//發送結果
                    //dialog.dismiss();//如果使用方法1,需要手動關閉dialog
                }
            })
            .create();

alertDialog.setOnShowListener(new DialogInterface.OnShowListener() {
    @Override
    public void onShow(DialogInterface dialog) {
        //canNotCloseDialog(dialog);//方法1

        final Button btNegative = alertDialog.getButton(AlertDialog.BUTTON_NEGATIVE);
        btNegative.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (isSetData) {
                    btNegative.setText(R.string.dialog_to_time);
                    datePicker.setVisibility(View.VISIBLE);
                    timePicker.setVisibility(View.INVISIBLE);
                    isSetData = false;
                } else {
                    btNegative.setText(R.string.dialog_to_date);
                    datePicker.setVisibility(View.INVISIBLE);
                    timePicker.setVisibility(View.VISIBLE);
                    isSetData = true;
                }
            }
        });
    }
});
alertDialog.setCanceledOnTouchOutside(false);
           

結束語

如果您覺得這篇文章能夠幫助到您,請幫忙頂一下,您的鼓勵是對我的最大支援!

如需轉載請标明出處。

繼續閱讀