根据您的评论,应该很容易保护OnTimeSetListener
带有布尔值的回调,以防止您的逻辑在单击“取消”的情况下运行。
我快速浏览了您的代码,以下内容似乎工作正常:
private boolean mIgnoreTimeSet = false;
final TimePickerDialog timeDlg = new TimePickerDialog(PreferencesActivity.this, PreferencesActivity.this, hour, min, true);
// Make the Set button
timeDlg.setButton(DialogInterface.BUTTON_POSITIVE, "Set", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
mIgnoreTimeSet = false;
// only manually invoke OnTimeSetListener (through the dialog) on pre-ICS devices
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.ICE_CREAM_SANDWICH) timeDlg.onClick(dialog, which);
Toast.makeText(getApplicationContext(), "Set", Toast.LENGTH_SHORT).show();
}
});
// Set the Cancel button
timeDlg.setButton(DialogInterface.BUTTON_NEGATIVE, "Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(getApplicationContext(), "Cancel", Toast.LENGTH_SHORT).show();
mIgnoreTimeSet = true;
dialog.cancel();
}
});
timeDlg.show();
@Override public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
if (mIgnoreTimeSet) return;
// get the values here - this will only run if 'Set' was clicked
}
为了举例,我假设你的PreferencesActivity
实施OnTimeSetListener
. Since onTimeSet(...)
之后被呼叫onClick(...)
,您可以简单地切换一个布尔值,该布尔值将确定您是否应该对回调中的值执行某些操作,或者只是忽略它们。
我必须承认它并不理想,但至少很实用。假期结束后,我将尝试再次寻找“更好”的解决方案。
一种替代方法是使用反射来获取内部使用的句柄TimePicker
widget,但这在未来的 Android 版本中更有可能被破坏。
// 编辑:潜在的替代方案? (未测试)
第二种选择,可能有点“干净”:extendTimePickerDialog
并覆盖(空)公共方法:
public void onTimeChanged(TimePicker view, int hourOfDay, int minute)
在那里,跟踪用户设置的一天中的小时和分钟,并实现两个返回它们的 getter。然后,只有在单击肯定按钮时才从对话框中获取这些值,但如果单击“取消”,则会失败。基本上你不需要OnTimeSetListener
不再这样了,因此它是否被调用并不重要。
// Edit2:支持 ICS 之前的设备
在收到一些关于提议的解决方案不适用于 ICS 之前的设备的评论后,我对上述代码做了一个小小的更改 - 即使它不在原始问题的范围内。
pre-ICS 和 post-ICS 设备之间的主要区别在于OnTimeSetListener
对话框按钮后不会自动调用回调onClick()
方法已运行。一个简单的解决方法是调用onClick()
对话框上的方法,然后将调用侦听器。在上面的解决方案中,我添加了版本代码检查,因为否则您的侦听器最终将在后 ICS 设备上被调用两次,这可能会导致不良的副作用。
在 Android 2.1-update1 和 Android 4.2.2 上测试并确认了行为。