【问题标题】:Dismiss DatePickerDialog on pressing back button按下返回按钮时关闭 DatePickerDialog
【发布时间】: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 的方法来处理未设置数据的情况。

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

谢谢。

【问题讨论】:

    标签: android android-fragments


    【解决方案1】:

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

    中进行了讨论

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

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

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

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2016-02-03
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2017-02-16
            相关资源
            最近更新 更多