【问题标题】:Is there a way to use cancel in Android JellyBean TimePickerDialog?有没有办法在 Android JellyBean TimePickerDialog 中使用取消?
【发布时间】:2012-12-15 01:14:42
【问题描述】:

据我所知,Jelly Beans 之前的版本在使用 TimePickerDialog 时具有 SetCancel 按钮。 Jelly Beans 只有 Done 按钮。

我可以离开 Done 按钮,并可以通过在对话框外部单击来关闭对话框,但是如果按 Done 或在对话框外部,我的 onTimeSetListener 会被调用.

所以我发现 this stackoverflow question 描述了使用 DatePickerDialog 时存在错误。要使用 DatePickerDialog 解决问题,在初始化时我必须将 onDateSetListener 设置为 null,并实现我自己的按钮来处理 BUTTON_POSITIVE(设置)和 BUTTON_NEGATIVE(取消) onClick 方法。这很好,因为当按钮 Set 被调用时,我可以像这样访问 DatePicker

int yearPicked = dateDlg.getDatePicker().getYear();
int monthPicked = dateDlg.getDatePicker().getMonth();
int dayPicked = dateDlg.getDatePicker().getDayOfMonth();

所以没有必要使用onDateSetListener,但如果我愿意,它会在按下设置或取消时再次被调用。

我尝试以相同的方式使用 TimePickerDialog,但问题是,在 BUTTON_POSITIVE onClick 方法中,我无法像以前一样访问小时和分钟值,因为 TimePickerDialog 不提供 TimePicker,因为 DatePickerDialog 提供 DatePicker。再说一次,如果我使用onTimeSetListener,它会被按任何东西调用。

Calendar cal = Calendar.getInstance();

int hour = cal.get(Calendar.HOUR_OF_DAY);
int min = cal.get(Calendar.MINUTE);

final TimePickerDialog timeDlg = new TimePickerDialog(PreferencesActivity.this, null, hour, min, true);

// Make the Set button
timeDlg.setButton(DialogInterface.BUTTON_POSITIVE, "Set", new DialogInterface.OnClickListener() {
    public void onClick(DialogInterface dialog, int which) {
        if (which == DialogInterface.BUTTON_POSITIVE) {
            // CANNOT ACCES THE VALUES
            Toast.makeText(PreferencesActivity.this, "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) {
        if (which == DialogInterface.BUTTON_NEGATIVE) {
            Toast.makeText(PreferencesActivity.this, "Cancel", Toast.LENGTH_SHORT).show();
        }
    }
});

timeDlg.show();

【问题讨论】:

  • 好吧,您仍然可以注册TimePickerDialog.OnTimeSetListener 来捕获输入的值,但如果点击否定按钮,就不要对它们做任何事情,对吧?
  • 就是问题所在,OnTimeSetListener 是在按下正负后退按钮时调用的。
  • 我遇到了同样的问题,请注意下面接受的答案不向后兼容(pre jb)。我需要 sdk 8+,我在扩展片段对话框中使用布尔值解决了它,并在那里覆盖了 onClick()。

标签: android android-4.2-jelly-bean timepicker


【解决方案1】:

根据您的评论,使用布尔值保护 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。由于onTimeSet(...)onClick(...) 之后被调用,因此您可以简单地切换一个布尔值,该布尔值将确定您是应该对回调中的值执行操作还是忽略它们。

我不得不承认这并不理想,但至少可以发挥作用。假期过后,我将尝试重新审视“更好”的解决方案。

另一种方法是使用反射来处理内部使用的 TimePicker 小部件,但这在未来的 Android 版本中更有可能中断。


// 编辑:潜在的替代方案? (未测试)

第二种选择,可能有点“干净”:扩展 TimePickerDialog 并覆盖(空)公共方法:

public void onTimeChanged(TimePicker view, int hourOfDay, int minute)

在那里,跟踪用户设置的一天中的小时和分钟,并实现两个返回它们的 getter。然后,如果单击了肯定按钮,则仅从对话框中获取这些值,但只是通过“取消”。基本上,您将不再需要OnTimeSetListener,因此它是否被调用都无关紧要。


// Edit2:支持 ICS 之前的设备

在收到一些关于提议的解决方案在 ICS 之前的设备上不起作用的评论后,我对上面的代码做了一个小改动——即使它不在原始问题的范围内。

前 ICS 设备和后 ICS 设备之间的主要区别在于,在对话框按钮的 onClick() 方法运行后不会自动调用 OnTimeSetListener 回调。一个简单的解决方法是调用对话框上的onClick() 方法,然后调用监听器。在上面的解决方案中,我添加了版本代码检查,否则您的侦听器最终会在后 ICS 设备上被调用两次,这可能会导致不良副作用。

在 Android 2.1-update1 和 Android 4.2.2 上测试并确认行为。

【讨论】:

  • 感谢您的回答,花一天时间玩代码和搜索。布尔值的技巧很好用。我的 PreferecesActivity 没有实现 OnTimeListener,但我明白了。
  • @AdilMalik:在阅读了一些 cmets 说建议的解决方案不适用于 ICS 之前的设备后,我做了一个小改动来适应这一点。详情请参阅第二次编辑。
【解决方案2】:

我在 Nexus 7 上遇到与 Jelly Bean 的 TimePickerDialog 相同的“仅按钮完成”问题时发现了这个线程(我的 Nexus One,Gingerbread,在同一个 TimePickerDialog 上有设置和取消按钮)。但是,在我的 Nexus 7(内部版本号 JWR66Y)上对 4.3 Jelly Bean 进行后续更新后,正确的按钮设置和取消似乎已经返回。

然而,在研究这个问题时,我确实遇到了这个Stackoverflow thread,它相当细致地概述了 DatePickerDialog 的更大问题(在引用的错误报告中指出了 TimePickerDialog 的类似问题)并提供了解决方案。

请注意,必须仔细考虑使用这些对话框,因为它们在某些版本的 Android 中无法正常运行(根据其作者的说法,上述线程中提供的解决方案并未在“生产代码中”使用)。

【讨论】:

  • 很高兴听到最新版本已解决该问题。谢谢
猜你喜欢
  • 1970-01-01
  • 2014-10-07
  • 1970-01-01
  • 2012-08-22
  • 1970-01-01
  • 1970-01-01
  • 2012-11-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多