按下返回按钮时关闭DatePickerDialog

6
在我的视图中,我有一个按钮,按下该按钮会弹出一个DatePickerDialog。弹出的对话框上有一个“完成”按钮。当我按下该按钮时,所选日期将填充到EditText框中。
现在,当我按下返回按钮(Back button),它仍会将日期填充到EditText中。如何在不返回任何值的情况下关闭对话框。
这是我得到的代码-
调用片段的活动:
public class TransactionActivity extends FragmentActivity implements iRibbonMenuCallback {        
    .....
    public void selectDate(View view) { 
        // This is the method invoked by the button
        SelectDateFragment newFragment = new SelectDateFragment();
        newFragment.show(getSupportFragmentManager(), "DatePicker");
    }

    public void populateSetDate(int year, int month, int day) {
        // Puts the date in the EditText box
        mEdit = (EditText)findViewById(R.id.DateText);
        mEdit.setText(month+"/"+day+"/"+year);
    }
}

对话框的片段(基于Android API指南上的此页面):

public class SelectDateFragment extends DialogFragment implements DatePickerDialog.OnDateSetListener {
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        final Calendar calendar = Calendar.getInstance();
        int yy = calendar.get(Calendar.YEAR);
        int mm = calendar.get(Calendar.MONTH);
        int dd = calendar.get(Calendar.DAY_OF_MONTH);
        return new DatePickerDialog(getActivity(), this, yy, mm, dd);
    }

    public void onDateSet(DatePicker view, int yy, int mm, int dd) {
             // Calls a method on the activity which invokes this fragment
         ((TransactionActivity)getActivity()).populateSetDate(yy, mm+1, dd);    

    }
}

似乎没有类似于onDataSet方法来处理未设置数据的情况。

有没有一种方法可以在不获取日期选择器值的情况下取消/关闭弹出的日期选择器?

谢谢。

8个回答

6
看起来在Jellybean存在一个错误,即取消按钮不起作用(因此返回按钮也不起作用)。这在Jelly Bean DatePickerDialog --- is there a way to cancel?中讨论过。 David Cesarino在上述帖子中报告了错误和解决方法,并在这里SO中发布了他的解决方案。 cavega稍微修改了上述解决方案,以允许在DatePickerDialog中将日期初始化为除今天之外的其他日期。可以在这里找到代码。我使用了他的解决方案,成功了。

3
我也曾经遇到过这个问题,但解决方案非常简单。DialogFragment实现了DialogInterface.OnCancelListener和DialogInterface.OnDismissListener接口,因为DialogInterface.OnCancelListener.onCancel在DialogInterface.OnDismissListener.onDismiss之前被调用,所以你可以在onCancel中清除日期值,并且仅当日期值不为0时才在onDismiss中调用TransactionActivity.populateSetDate方法。
另外:为了使Fragment更加独立,最好的做法是Fragment定义一个公共接口,调用Activity必须实现该接口,这样你就可以在接口上调用populateSetDate方法,而不是在Activity上调用。
请参见下面的代码实现onCancel和onDismiss:
public class SelectDateFragment extends DialogFragment
  implements DatePickerDialog.OnDateSetListener
{

  private int year;
  private int month;
  private int day;

  @Override
  public Dialog onCreateDialog(Bundle savedInstanceState) {
    final Calendar calendar = Calendar.getInstance();
    int yy = calendar.get(Calendar.YEAR);
    int mm = calendar.get(Calendar.MONTH);
    int dd = calendar.get(Calendar.DAY_OF_MONTH);
    return new DatePickerDialog(getActivity(), this, yy, mm, dd);
  }

  public void onDateSet(DatePicker view, int yy, int mm, int dd) {
    // Calls a method on the activity which invokes this fragment
    // ((TransactionActivity)getActivity()).populateSetDate(yy, mm+1, dd); 
    year = yy;
    month = mm;
    day = dd;
  }

  // Gets called before onDismiss, so we can erase the selectedDate
  @Override
  public void onCancel(DialogInterface dialog) {
    year = 0;
    month = 0;
    day = 0;
  }


  @Override
  public void onDismiss(DialogInterface dialog) {
    if (year != 0) {
      ((TransactionActivity)getActivity()).populateSetDate(year, month + 1, day);
    }
  }
}

3

我写了一个简单的标准DatePickerDialog的替代品,对于我来说运行良好:

/**
 * Enhanced date picker dialog. Main difference from ancestor is that it calls
 * OnDateSetListener only when when pressing OK button, and skips event when closing with
 * BACK key or by tapping outside a dialog.
 */
public class IBSDatePickerDialog extends DatePickerDialog {

    public IBSDatePickerDialog(final Context context, final OnDateSetListener callBack, final int year, final int monthOfYear, final int dayOfMonth) {
        super(context, callBack, year, monthOfYear, dayOfMonth);
    }

    public IBSDatePickerDialog(final Context context, final int theme, final OnDateSetListener callBack, final int year, final int monthOfYear, final int dayOfMonth) {
        super(context, theme, callBack, year, monthOfYear, dayOfMonth);
    }

    @Override
    public void onClick(final DialogInterface dialog, final int which) {
        // Prevent calling onDateSet handler when clicking to dialog buttons other, then "OK"
        if (which == DialogInterface.BUTTON_POSITIVE)
            super.onClick(dialog, which);
    }

    @Override
    protected void onStop() {
        // prevent calling onDateSet handler when stopping dialog for whatever reason (because this includes
        // closing by BACK button or by tapping outside dialog, this is exactly what we try to avoid)

        //super.onStop();
    }
}

使用对话框示例(免费奖励:将取消按钮添加到对话框以获得更好的可用性):

public static class datePickerFragment extends DialogFragment implements DatePickerDialog.OnDateSetListener {

    @Override
    public Dialog onCreateDialog(final Bundle savedInstanceState) {

        Calendar cal = Calendar.getInstance();
        IBSDatePickerDialog dlg = new IBSDatePickerDialog(myActivity, this, cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), cal.get(Calendar.DAY_OF_MONTH));

        // Add Cancel button into dialog
        dlg.setButton(DialogInterface.BUTTON_NEGATIVE, "Cancel", (OnClickListener) null);

        return dlg;
    }

    @Override
    public void onDateSet(final DatePicker view, final int year, final int month, final int day) {
        // TODO: do whatever you want with date selected
    }
}

public void showDatePickerDialog() {
    final datePickerFragment f = new datePickerFragment();
    f.show(getSupportFragmentManager(), "datePicker");
}

1
public class pickerdate extends Activity {
/** Called when the activity is first created. */
  private TextView mDateDisplay;
    private Button mPickDate;
    private int mYear;
    private int mMonth;
    private int mDay;

    static final int DATE_DIALOG_ID = 0;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);


        mDateDisplay = (TextView) findViewById(R.id.dateDisplay);
        mPickDate = (Button) findViewById(R.id.pickDate);


        mPickDate.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                showDialog(DATE_DIALOG_ID);
            }
        });


        final Calendar c = Calendar.getInstance();
        mYear = c.get(Calendar.YEAR);
        mMonth = c.get(Calendar.MONTH);
        mDay = c.get(Calendar.DAY_OF_MONTH);

        updateDisplay();
    }
    private void updateDisplay() {
        mDateDisplay.setText(
            new StringBuilder()
                    // Month is 0 based so add 1
                    .append(mMonth + 1).append("-")
                    .append(mDay).append("-")
                    .append(mYear).append(" "));
    }
    private DatePickerDialog.OnDateSetListener mDateSetListener =
        new DatePickerDialog.OnDateSetListener() {

            public void onDateSet(DatePicker view, int year, 
                                  int monthOfYear, int dayOfMonth) {
                mYear = year;
                mMonth = monthOfYear;
                mDay = dayOfMonth;
                updateDisplay();
            }
        };
        @Override
        protected Dialog onCreateDialog(int id) {
            switch (id) {
            case DATE_DIALOG_ID:
                return new DatePickerDialog(this,
                            mDateSetListener,
                            mYear, mMonth, mDay);
            }
            return null;
        }
 }

上面的代码对我有用。对话框有设置和取消按钮。设置将设置日期,取消将关闭对话框。根据您的需求进行修改。点击返回按钮也会关闭对话框。

我正在使用片段来实现我的方法,如果我没错的话,这应该是适用于Android 4.0及以上版本的最佳途径。 - Bharat
你的意思是说上面的代码在Fragment中不能用吗?其实上面的代码应该可以在Fragment中使用。虽然我没有试过,但理论上应该是可以的。我不认为这段代码在Fragment中会有任何问题。或许其他人可以帮你解决这个问题。 - Raghunandan

0

不必实现自定义DatePickerDialog,您可以为正按钮实现自定义OnClickListener:

DatePickerDialog dateDialog = new DatePickerDialog(this, null, year, month, day);
datePickerDialog.setButton(DialogInterface.BUTTON_POSITIVE,
    getResources().getString(R.string.text_done),
    new OnDoneClickListener(datePickerDialog));

// <...>

private class OnDoneClickListener implements DialogInterface.OnClickListener {

        private DatePickerDialog mPickerDialog;

        BirthDatePickerDialog(DatePickerDialog mPickerDialog) {
            this.mPickerDialog = mPickerDialog;
        }

        @Override
        public void onClick(DialogInterface dialog, int which) {
            SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");
            Calendar cal = Calendar.getInstance();
            DatePicker picker =  mPickerDialog.getDatePicker();
            cal.set(Calendar.YEAR, picker.getYear());
            cal.set(Calendar.MONTH, picker.getMonth());
            cal.set(Calendar.DAY_OF_MONTH, picker.getDayOfMonth());
            spinnerDateBirth.setText(dateFormat.format(cal.getTime()));
        }
}

点击空白区域或返回键将关闭对话框,不做任何操作。


0

我想你是在问这个

 setOnCancelListener(new OnCancelListener() {
                @Override
                public void onCancel(DialogInterface dialog) {
    }

这似乎没有起作用。这是我尝试的代码:dialog.setOnKeyListener(new Dialog.OnKeyListener() { @Override public boolean onKey(DialogInterface arg0, int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK) { dialog.dismiss(); } return false; } }); - Bharat

0
你可以尝试在你的AlertDialog中加入以下内容:
如果你取消了对话框,mEdit将会返回为空。 mEdit.setText("");
 AlertDialog alertDialog;

    alertDialog.setOnCancelListener(new OnCancelListener() 
    {                   
           @Override
            public void onCancel(DialogInterface dialog) 
             {
               // TODO Auto-generated method stub
                    mEdit.setText(""); 
                    dialog.dismiss();                           

            }
});

DatePickerDialog似乎没有onCancel方法。这是我的代码:最终的DatePickerDialog dialog = new DatePickerDialog(getActivity(), this, yy, mm, dd); dialog.setOnCancelListener(new OnCancelListener() { ...} 在eclipse中,我收到了“not applicable for the arguments”的消息。 - Bharat
对不起,我把这个弄错了。 - IssacZH.

0

使用以下方法,当用户按下返回按钮时调用。此方法属于Activity

@Override
public void onBackPressed() {
    // TODO Auto-generated method stub
    super.onBackPressed();

    dialog.dismiss();
}

我在一个Fragment类中使用了DatePickerDialog。代码如下:public class SelectDateFragment extends DialogFragment。但是,我发现在DialogFragment协议中没有onBackPressed()方法。Eclipse提示:The method onBackPressed() of type SelectDateFragment must override or implement a supertype method - Bharat
但是在FragmentActivity中有一个方法。您认为您可以在DialogFragment中创建一个侦听器,当活动收到后退按钮按下事件时,您触发一个侦听器吗? - Chintan Rathod

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接