有没有办法在Android JellyBean TimePickerDialog中使用cancel?

时间:2012-12-30 15:50:57

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

据我所知,在使用 TimePickerDialog 时,Jelly Beans之前的版本有 Set Cancel 按钮。 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,但是如果我愿意的话,按下Set或Cancel时会再次调用它。

我尝试以相同的方式使用 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();

2 个答案:

答案 0 :(得分:8)

根据您的评论,使用布尔值保护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前设备上工作的建议解决方案的几点评论之后,我对上述代码做了一些小改动 - 即使很难,也不在原始问题的范围内。

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

在Android 2.1-update1和Android 4.2.2上经过测试和确认的行为。

答案 1 :(得分:1)

在我的Nexus 7(我的Nexus One,Gingerbread,同一个TimePickerDialog的Set和Cancel按钮)上遇到与Jelly Bean的TimePickerDialog相同的“Done-button-only”问题时,我找到了这个帖子。但是,随着我的Nexus 7(内部版本号JWR66Y)上的4.3 Jelly Bean的后续更新,似乎已经返回了正确的按钮Set和Cancel。

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

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