如何在Android中为日期选择器的取消按钮创建一个监听器?

9

我正在使用Android中的日期选择器,让用户选择日期。如果用户选择并设置日期(我已经成功实现了这一点),我希望它执行一项操作,然后在用户按下日期选择器上的取消按钮(打开日期选择器,但随后取消)时清除某个文本字段。

我一直在尝试的方法是创建一个

private DatePickerDialog.OnCancelListener mDateCancelListener =
    new DatePickerDialog.OnCancelListener() {
        public void onCancel(DialogInterface dialog) {
            timeClear(); //method that clears text field
        }

    };

然后我执行

TimePickerDialog timeDialog = new TimePickerDialog(this,
  mTimeSetListener,
  c.get(Calendar.HOUR),
  c.get(Calendar.MINUTE),
  false);
timeDialog.setOnCancelListener(mTimeCancelListener);

附加监听器。

我的问题是,如果用户按下后退按钮,则侦听器起作用,但如果他们按下取消按钮,则不起作用。我尝试使用dismiss监听器,它可以工作,除了我设置或取消datepicker时它仍然会触发!

我需要做什么才能仅在我按下datepicker上的取消按钮时触发某些操作?


我正在尝试使用日期选择器完成完全相同的操作。在下面提出的解决方案中,应用程序崩溃,因为.getButton(TimePickerDialog.BUTTON_NEGATIVE)返回null。有没有人有解决这个问题的方法? - Kenneth Baltrinic
1
请检查此链接:https://dev59.com/znA85IYBdhLWcg3wHv3B - W00di
6个回答

5
唯一的解决方案有些反直觉,就是你需要“覆盖”取消按钮:
    timeDialog.setButton(DialogInterface.BUTTON_NEGATIVE,
            getString(R.string.cancel),
            new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int which) {
                    // do stuff
                }
            });

这也调用了OnTimeSet方法。因此,它按顺序调用负侦听器,然后是正侦听器。 - Ganesh Krishnan

2

经过一些实验,我发现需要一个OnDismissListener,如下所示。请注意,我为TimePickerDialog开发了解决方案,但setOnDismissListener是从Dialog继承的,因此对于DatePickerDialog应该也适用。

timeDialog.setOnDismissListener(mOnDismissListener);


private DialogInterface.OnDismissListener mOnDismissListener =
    new DialogInterface.OnDismissListener() {
        public void onDismiss(DialogInterface dialog) {
            _logger.v("mOnDismissListener called");
            timeClear();
        }
    };

我已经测试过它并且它有效。事实上,我发现在你提到的两种情况下,即当用户点击取消按钮和按下硬件返回按钮时,OnDismissListener都会被调用。因此,你只需要这个处理程序。
最后,现在我知道要搜索什么,我找到了这篇文章,它描述了OnDismissListener和OnCancelListener之间的区别,在“使用Dismiss Listeners”部分中:(链接)

这不是被要求的 - 无论按下哪个按钮,onDismiss都会被触发,但发布者想知道何时按下取消按钮。他们还表示已经尝试过onDismiss监听器。 - barry
@barry 很好的观点。我发现有趣的是,“onCancelListener”与datePicker对话框上的取消按钮无关。 W00di的评论是正确答案...可能是重复的。 - angryITguy

2
您可以创建一个布尔变量isDataSet,在dateSetListener中执行isDataSet = true;,然后使用以下代码附加onDismissListener:
if(isDataSet)
    //Data was set and neither back nor cancel button was clicked
else
    //back or cancel button was clicked

但是不要忘记每次创建对话框时将isDataSet设置为false。


1
这是解决方案。它可能对其他人有帮助。
 datePickerDialog.setButton(DialogInterface.BUTTON_NEGATIVE, "cancel", new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog, int which) {
            if (which == DialogInterface.BUTTON_NEGATIVE) {
                // do something
            }
        }
    });

0

试试这个:

timeDialog.getButton(TimePickerDialog.BUTTON_NEGATIVE).setOnClickListener(mTimeCancelListener);

你需要将 mTimeCancelListener 更改为实现 DialogInterface.OnClickListener 而不是 OnCancelListener


谢谢您的回复!我还是有一点困难。如果我创建一个DialogInterface.OnClickListener并尝试将其用于TimePicker,它会告诉我需要先进行强制转换。如果我这样做,那么当您单击打开TimePicker的按钮时,程序就会崩溃。如果您不这样做,则会显示以下内容:setOnClickListener(android.view.View.OnClickListener)在android.view.View中无法应用于(android.content.DialogInterface.OnClickListener) timeDialog.getButton(TimePickerDialog.BUTTON_NEGATIVE).setOnClickListener(dateTimeClickCancelListener); - Adam
我尝试创建一个View.OnClickListner()而不是DialogInterfaceListener,但当我尝试打开TimePicker dialog时,程序会崩溃。 - Adam

0
完整的解决方案(经过测试并且可行)是将OnDismissListener(参见Kenneth Baltrinic的答案3)与dilix描述的onDateSet布尔值(上面的1个答案)结合使用。你需要两者,因为onDismiss在所有情况下都会被使用: (1)用户已选择实际数据 (2)用户已取消 (3)用户已按下硬件返回按钮。
使用这种组合可以使您区分它们。

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