dav*_*ino 147 android datepicker android-datepicker android-4.2-jelly-bean
--- 主持人注意:今天(7月15日),我注意到有人在这里遇到过这个问题.但是我不确定将这个作为副本关闭是否合适,因为我认为我提供了一个更好的解释.我不确定是否应该编辑其他问题并将其粘贴到那里,但我不太愿意过多地改变别人的问题.---
我有一些奇怪的东西.
我不认为问题取决于您构建的SDK.设备操作系统版本是重要的.
DatePickerDialog
在Jelly Bean中被更改了(?),现在只提供了一个Done按钮.以前的版本包括一个取消按钮,这可能会影响用户体验(不一致,以前Android版本的肌肉记忆).
复制:创建一个基本项目.把它放进去onCreate
:
DatePickerDialog picker = new DatePickerDialog(
this,
new OnDateSetListener() {
@Override
public void onDateSet(DatePicker v, int y, int m, int d) {
Log.d("Picker", "Set!");
}
},
2012, 6, 15);
picker.show();
Run Code Online (Sandbox Code Playgroud)
预期:在对话框中显示"取消"按钮.
当前:一个取消按钮不会出现.
Dialog会调用它应该调用的侦听器,然后始终调用OnDateSetListener
侦听器.取消仍然调用set方法,并设置它调用方法两次.
复制:使用#1代码,但在下面添加代码(您将看到这解决了#1,但只能在视觉上/ UI):
picker.setButton(DialogInterface.BUTTON_NEGATIVE, "Cancel",
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Log.d("Picker", "Cancel!");
}
});
Run Code Online (Sandbox Code Playgroud)
预期:
当前:
显示行为的日志行:
07-15 12:00:13.415: D/Picker(21000): Set!
07-15 12:00:24.860: D/Picker(21000): Cancel!
07-15 12:00:24.876: D/Picker(21000): Set!
07-15 12:00:33.696: D/Picker(21000): Set!
07-15 12:00:33.719: D/Picker(21000): Set!
Run Code Online (Sandbox Code Playgroud)
DatePickerFragment
并不重要.我为你简化了问题,但我已经测试过了.dav*_*ino 115
注意:固定为Lollipop,源于此处.用于客户端的自动类(与所有Android版本兼容)也已更新.
OnDateSetListener
在您的活动中实施(或根据您的需要更改课程).使用此代码触发对话框(在此示例中,我在其中使用它Fragment
):
Bundle b = new Bundle();
b.putInt(DatePickerDialogFragment.YEAR, 2012);
b.putInt(DatePickerDialogFragment.MONTH, 6);
b.putInt(DatePickerDialogFragment.DATE, 17);
DialogFragment picker = new DatePickerDialogFragment();
picker.setArguments(b);
picker.show(getActivity().getSupportFragmentManager(), "frag_date_picker");
Run Code Online (Sandbox Code Playgroud)这就是全部!我仍然保持我的答案"被接受"的原因是因为我仍然更喜欢我的解决方案,因为它在客户端代码中占用的空间非常小,它解决了基本问题(在框架类中调用了监听器),在配置更改中工作得很好它将代码逻辑路由到以前未受此bug影响的Android版本中的默认实现(请参阅类源代码).
好吧,看起来确实是一个错误而其他人已经填满了它.问题34833.
我发现问题可能在于DatePickerDialog.java
.它的内容如下:
private void tryNotifyDateSet() {
if (mCallBack != null) {
mDatePicker.clearFocus();
mCallBack.onDateSet(mDatePicker, mDatePicker.getYear(),
mDatePicker.getMonth(), mDatePicker.getDayOfMonth());
}
}
@Override
protected void onStop() {
tryNotifyDateSet();
super.onStop();
}
Run Code Online (Sandbox Code Playgroud)
我猜它可能是:
@Override
protected void onStop() {
// instead of the full tryNotifyDateSet() call:
if (mCallBack != null) mDatePicker.clearFocus();
super.onStop();
}
Run Code Online (Sandbox Code Playgroud)
现在,如果有人能告诉我如何向Android提出补丁/错误报告,我会很高兴.与此同时,我提出了一个可能的修复(简单)作为问题的附加版本DatePickerDialog.java
.
null
在构造函数中设置侦听器,BUTTON_POSITIVE
稍后创建自己的按钮.就是这样,详情如下.
出现问题的原因是DatePickerDialog.java
,正如您在源代码中看到的那样,调用一个全局变量(mCallBack
)来存储在构造函数中传递的侦听器:
/**
* @param context The context the dialog is to run in.
* @param callBack How the parent is notified that the date is set.
* @param year The initial year of the dialog.
* @param monthOfYear The initial month of the dialog.
* @param dayOfMonth The initial day of the dialog.
*/
public DatePickerDialog(Context context,
OnDateSetListener callBack,
int year,
int monthOfYear,
int dayOfMonth) {
this(context, 0, callBack, year, monthOfYear, dayOfMonth);
}
/**
* @param context The context the dialog is to run in.
* @param theme the theme to apply to this dialog
* @param callBack How the parent is notified that the date is set.
* @param year The initial year of the dialog.
* @param monthOfYear The initial month of the dialog.
* @param dayOfMonth The initial day of the dialog.
*/
public DatePickerDialog(Context context,
int theme,
OnDateSetListener callBack,
int year,
int monthOfYear,
int dayOfMonth) {
super(context, theme);
mCallBack = callBack;
// ... rest of the constructor.
}
Run Code Online (Sandbox Code Playgroud)
因此,诀窍是提供一个null
监听器作为监听器存储,然后滚动你自己的一组按钮(下面是来自#1的原始代码,更新):
DatePickerDialog picker = new DatePickerDialog(
this,
null, // instead of a listener
2012, 6, 15);
picker.setCancelable(true);
picker.setCanceledOnTouchOutside(true);
picker.setButton(DialogInterface.BUTTON_POSITIVE, "OK",
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Log.d("Picker", "Correct behavior!");
}
});
picker.setButton(DialogInterface.BUTTON_NEGATIVE, "Cancel",
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Log.d("Picker", "Cancel!");
}
});
picker.show();
Run Code Online (Sandbox Code Playgroud)
现在它会起作用,因为我上面发布了可能的修正.
并且由于DatePickerDialog.java
检查null
它何时读取mCallback
(从API 3/1.5的日期看起来 ---当然不能检查Honeycomb),它不会触发异常.考虑到Lollipop解决了这个问题,我不打算研究它:只使用默认的实现(在我提供的类中提到).
起初我害怕不打电话clearFocus()
,但我已经在这里测试过,Log系统很干净.所以我提出的那条线毕竟可能根本不需要,但我不知道.
正如我在下面的评论中指出的那样,这是一个概念,您可以从我的Google云端硬盘帐户下载我正在使用的课程.我使用的方式,默认系统实现用于不受bug影响的版本.
我采取了一些适合我需要的假设(按钮名称等),因为我希望将客户端类中的样板代码减少到最少.完整用法示例:
class YourActivity extends SherlockFragmentActivity implements OnDateSetListener
// ...
Bundle b = new Bundle();
b.putInt(DatePickerDialogFragment.YEAR, 2012);
b.putInt(DatePickerDialogFragment.MONTH, 6);
b.putInt(DatePickerDialogFragment.DATE, 17);
DialogFragment picker = new DatePickerDialogFragment();
picker.setArguments(b);
picker.show(getActivity().getSupportFragmentManager(), "fragment_date_picker");
Run Code Online (Sandbox Code Playgroud)
dmo*_*mon 16
我将在David Cesarino发布的解决方案中添加我自己的riff,以防你没有使用Fragments,并希望在所有版本(2.1至4.1)中轻松修复它:
public class FixedDatePickerDialog extends DatePickerDialog {
//I use a Calendar object to initialize it, but you can revert to Y,M,D easily
public FixedDatePickerDialog(Calendar dateToShow, Context context, OnDateSetListener callBack) {
super(context, null, dateToShow.get(YEAR), dateToShow.get(MONTH), dateToShow.get(DAY_OF_MONTH));
initializePicker(callBack);
}
public FixedDatePickerDialog(Calendar dateToShow, Context context, int theme,
OnDateSetListener callBack) {
super(context, theme, null, dateToShow.get(YEAR), dateToShow.get(MONTH), dateToShow.get(DAY_OF_MONTH));
initializePicker(callBack);
}
private void initializePicker(final OnDateSetListener callback) {
try {
//If you're only using Honeycomb+ then you can just call getDatePicker() instead of using reflection
Field pickerField = DatePickerDialog.class.getDeclaredField("mDatePicker");
pickerField.setAccessible(true);
final DatePicker picker = (DatePicker) pickerField.get(this);
this.setCancelable(true);
this.setButton(DialogInterface.BUTTON_NEGATIVE, getContext().getText(android.R.string.cancel), (OnClickListener) null);
this.setButton(DialogInterface.BUTTON_POSITIVE, getContext().getText(android.R.string.ok),
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
picker.clearFocus(); //Focus must be cleared so the value change listener is called
callback.onDateSet(picker, picker.getYear(), picker.getMonth(), picker.getDayOfMonth());
}
});
} catch (Exception e) { /* Reflection probably failed*/ }
}
}
Run Code Online (Sandbox Code Playgroud)
小智 8
在修复bug之前,我建议不要使用DatePickerDialog或TimePickerDialog.使用自定义AlertDialog和TimePicker/DatePicker小部件;
更改TimePickerDialog;
final TimePicker timePicker = new TimePicker(this);
timePicker.setIs24HourView(true);
timePicker.setCurrentHour(20);
timePicker.setCurrentMinute(15);
new AlertDialog.Builder(this)
.setTitle("Test")
.setPositiveButton(android.R.string.ok, new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Log.d("Picker", timePicker.getCurrentHour() + ":"
+ timePicker.getCurrentMinute());
}
})
.setNegativeButton(android.R.string.cancel,
new OnClickListener() {
@Override
public void onClick(DialogInterface dialog,
int which) {
Log.d("Picker", "Cancelled!");
}
}).setView(timePicker).show();
Run Code Online (Sandbox Code Playgroud)
用;更改DatePickerDialog;
final DatePicker datePicker = new DatePicker(this);
datePicker.init(2012, 10, 5, null);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
datePicker.setCalendarViewShown(false);
}
new AlertDialog.Builder(this)
.setTitle("Test")
.setPositiveButton(android.R.string.ok, new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Log.d("Picker", datePicker.getYear() + " "
+ (datePicker.getMonth() + 1) + " "
+ datePicker.getDayOfMonth());
}
})
.setNegativeButton(android.R.string.cancel,
new OnClickListener() {
@Override
public void onClick(DialogInterface dialog,
int which) {
Log.d("Picker", "Cancelled!");
}
}).setView(datePicker).show();
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
28123 次 |
最近记录: |