按下返回按钮时关闭 DatePickerDialog

Posted

技术标签:

【中文标题】按下返回按钮时关闭 DatePickerDialog【英文标题】:Dismiss DatePickerDialog on pressing back button 【发布时间】:2013-02-23 16:20:06 【问题描述】:

在我看来,我有一个按钮,按下它会弹出一个 DatePickerDialog。弹出的对话框有一个“完成”按钮。当我按下该按钮时,所选日期将填充到 EditText 框中。

现在,当我按下返回按钮 () 时,它仍会在 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);
    

Dialog 的片段(基于 android API 指南上的this 页面):

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 的方法来处理未设置数据的情况。

有没有办法取消/关闭弹出的日期选择器而不获取它的价值?

谢谢。

【问题讨论】:

【参考方案1】:

Jelybean 似乎存在一个错误,即取消按钮不起作用(因此返回按钮)。这在Jelly Bean DatePickerDialog --- is there a way to cancel?

中进行了讨论

David Cesarino,在上述帖子中报告了错误和解决方法,并发布了他的解决方案here 和SO。

cavega 稍微修改了上述解决方案,以允许将 DatePickerDialog 中的日期初始化为今天以外的日期。代码可以找到here。我使用了他的解决方案并让它工作。

【讨论】:

【参考方案2】:

我编写了标准 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");

【讨论】:

【参考方案3】:

我也为此苦苦挣扎,但解决方案非常简单。 DialogFragment 实现了 DialogInterface.OnCancelListener 和 DialogInterface.OnDismissListener 并且因为 DialogInterface.OnCancelListener.onCancel 在 DialogInterface.OnDismissListener.onDismiss 之前被调用,所以您可以清除 onCancel 中的日期值并调用 onDismiss 中的 TransactionActivity.populateSetDate 方法,前提是日期值是不是 0。

顺便说一句:为了使 Fragment 更加独立,最好在 Fragment 定义一个调用 Activity 必须实现的公共接口,这样您就可以在该接口而不是 Activity 上调用 populateSetDate 方法。

有关 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);
    
  

【讨论】:

【参考方案4】:
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;
        
 

上面的代码对我有用。该对话框具有设置和取消按钮。设置将设置日期,取消将关闭对话框。根据您的需要进行相同的修改。单击后退按钮也将关闭对话框。

【讨论】:

我在我的方法中使用片段 & 我认为,如果我是对的,这就是 ICS 及更高版本的方法.. 你的意思是说以上在 Fragments 中不起作用??以上应该在片段中工作。我没试过。但它应该工作。我看不出有任何理由为什么这对 n 个片段不起作用。其他人可以用这个。【参考方案5】:

我想你是在问这个

 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; );【参考方案6】:

您可以尝试将其包含在您的 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 方法。这就是我所拥有的:final DatePickerDialog dialog = new DatePickerDialog(getActivity(), this, yy, mm, dd); dialog.setOnCancelListener(new OnCancelListener() ... 我在 eclipse 上收到 not applicable for the arguments 消息。 我的错。我把这个弄错了。【参考方案7】:

使用下面的方法,当用户按下返回按钮时调用。这个方法是Activity

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

    dialog.dismiss();

【讨论】:

我在 Fragment 类中有 DatePickerDialog。 public class SelectDateFragment extends DialogFragment。 onBackPressed() 似乎在 DialogFragment 的协议中没有方法。Eclipse 说 The method onBackPressed() of type SelectDateFragment must override or implement a supertype method 但是FragmentActivity中有一个方法。你不觉得你可以在DialogFragment 中创建一个监听器,当活动获得 Back 按钮按下事件时,你会触发一个监听器吗??【参考方案8】:

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

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()));
        

任何返回或点击空白区域都会关闭对话框,什么也不做。

【讨论】:

以上是关于按下返回按钮时关闭 DatePickerDialog的主要内容,如果未能解决你的问题,请参考以下文章

当用户按下键盘上的返回按钮时如何关闭键盘?

Android:如何在按下按钮时关闭一个活动并在按下另一个按钮时关闭整个后台堆栈? [复制]

如何在按下 UIButton 的按钮时关闭按钮阴影?

按下取消按钮时如何防止 UISearchController 关闭?

按下完成按钮时,PickerView 不会关闭

从活动结果意图按下后退按钮时应用程序关闭[关闭]