DatePicker Widget 不会占用 Nexus 6 上的整个 AlertDialog
DatePicker Widget does not take up entire AlertDialog on Nexus 6
我有一个使用非常简单的自定义布局的 DatePickerFragment。该布局在较小的设备(HTC One m7)上占据了整个警报对话框,但在 Nexus 6 上却没有。有谁知道为什么 DatePicker 没有占据 Nexus 6 警报对话框的整个宽度或从哪里开始进行故障排除?谢谢!
Nexus 6(注意日期 header 没有填满整个警报对话框)
HTC One m7
dialog_date.xml
<?xml version="1.0" encoding="utf-8"?>
<DatePicker xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/dialog_date_date_picker"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:calendarViewShown="false">
</DatePicker>
DatePickerFragment 的 onCreateDialog()
public Dialog onCreateDialog(Bundle savedInstanceState) {
Date date = (Date) getArguments().getSerializable(ARG_DATE);
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH);
int day = calendar.get(Calendar.DAY_OF_MONTH);
View v = LayoutInflater.from(getActivity())
.inflate(R.layout.dialog_date, null);
mDatePicker = (DatePicker)
v.findViewById(R.id.dialog_date_date_picker);
mDatePicker.init(year, month, day, null);
return new AlertDialog.Builder(getActivity())
.setView(v)
// .setTitle(R.string.date_picker_title)
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
int year = mDatePicker.getYear();
int month = mDatePicker.getMonth();
int day = mDatePicker.getDayOfMonth();
Date date = new GregorianCalendar(year, month, day).getTime();
sendResult(Activity.RESULT_OK, date);
}
})
.create();
}
警报对话框有一些严格的(奇怪的?)规则来控制它的大小。我不确定如何实际解决它,但有一个解决方法 - 显示对话框后,您可以强制其宽度与日期选择器的宽度相匹配。这为我解决了这个问题,希望它也对你有用:
public Dialog onCreateDialog(Bundle savedInstanceState) {
...
final AlertDialog alertDialog = new AlertDialog.Builder(getActivity())
...
.create();
alertDialog.setOnShowListener(new DialogInterface.OnShowListener() {
@Override public void onShow(DialogInterface dialog) {
WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
final Window window = getDialog().getWindow();
lp.copyFrom(window.getAttributes());
final View picker = window.findViewById(R.id.dialog_date_date_picker);
lp.width = picker.getWidth();
lp.height = picker.getHeight();
window.setAttributes(lp);
}
});
return alertDialog;
}
我无法使用 nitzanj 的建议使其工作,但我改变了创建 DatePickerDialog 的方式,它现在按预期工作。完整的来源如下。关键区别在于 onCreateDialog.
public class DatePickerFragment extends DialogFragment
implements DatePickerDialog.OnDateSetListener{
public static final String EXTRA_DATE =
"com.amicly.acaringtext.date";
private static final String ARG_DATE = "date";
@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
Date date = (Date) getArguments().getSerializable(ARG_DATE);
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH);
int day = calendar.get(Calendar.DAY_OF_MONTH);
return new DatePickerDialog(getActivity(), this, year, month, day);
}
public static DatePickerFragment newInstance(Date date) {
Bundle args = new Bundle();
args.putSerializable(ARG_DATE, date);
DatePickerFragment fragment = new DatePickerFragment();
fragment.setArguments(args);
return fragment;
}
private void sendResult(int resultCode, Date date) {
if (getTargetFragment() == null) {
return;
}
Intent intent = new Intent();
intent.putExtra(EXTRA_DATE, date);
getTargetFragment().
onActivityResult(getTargetRequestCode(), resultCode, intent);
}
@Override
public void onDateSet(DatePicker datePicker, int year, int month, int day) {
Date date = new GregorianCalendar(year, month, day).getTime();
sendResult(Activity.RESULT_OK, date);
}
}
如果有人为此苦恼(我肯定是在处理了六个小时之后),那么这可能对你有用。
不要使用带有 DatePicker 的 AlertDialog,而是使用 DatePickerDialog。不仅设置起来更容易,而且实际显示效果如预期。
用法示例:
DateTime dateTime = new DateTime();
new DatePickerDialog(
getActivity(),
R.style.DatePickerDialogCustom,
new DatePickerDialog.OnDateSetListener() {
@Override
public void onDateSet(DatePicker view, int year, int month, int dayOfMonth) {
dateTime = new DateTime(
year,
month + 1,
dayOfMonth,
dateTime.getHourOfDay(),
dateTime.getMinuteOfHour()
);
etDate.setText(dateFormatter.print(dateTime));
}
},
dateTime.getYear(),
dateTime.getMonthOfYear() - 1,
dateTime.getDayOfMonth()
).show();
月份偏移 1,因为 DatePicker returns 月份值介于 0 和 11 之间。
对于样式,请勿使用警告对话框样式。这实际上是导致原始问题的原因。如果不需要自定义样式,只需将其从构造函数中删除(不要使用 null)。如果您使用的是自定义样式,则只需在 styles.xml:
中创建一个新样式
<style name="DatePickerDialogCustom" parent="@style/Theme.AppCompat.Dialog">
<item name="android:colorBackground">@color/background</item>
<item name="colorAccent">@color/colorAccent</item>
<item name="android:datePickerStyle">@style/DatePickerCustom</item>
</style>
<style name="DatePickerCustom" parent="@android:style/Widget.Material.DatePicker">
<item name="android:headerBackground">@color/colorAccent</item>
</style>
我不知道同样的问题是否困扰着 TimePickers,但如果是的话,我想类似的解决方案会奏效。
原因是 AlertDialog 比子 DatePicker space 占用更多。
确保使用不带 .Alert
后缀的对话框主题(例如 Theme.AppCompat.Light.Dialog
)。
我有一个使用非常简单的自定义布局的 DatePickerFragment。该布局在较小的设备(HTC One m7)上占据了整个警报对话框,但在 Nexus 6 上却没有。有谁知道为什么 DatePicker 没有占据 Nexus 6 警报对话框的整个宽度或从哪里开始进行故障排除?谢谢!
Nexus 6(注意日期 header 没有填满整个警报对话框)
HTC One m7
dialog_date.xml
<?xml version="1.0" encoding="utf-8"?>
<DatePicker xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/dialog_date_date_picker"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:calendarViewShown="false">
</DatePicker>
DatePickerFragment 的 onCreateDialog()
public Dialog onCreateDialog(Bundle savedInstanceState) {
Date date = (Date) getArguments().getSerializable(ARG_DATE);
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH);
int day = calendar.get(Calendar.DAY_OF_MONTH);
View v = LayoutInflater.from(getActivity())
.inflate(R.layout.dialog_date, null);
mDatePicker = (DatePicker)
v.findViewById(R.id.dialog_date_date_picker);
mDatePicker.init(year, month, day, null);
return new AlertDialog.Builder(getActivity())
.setView(v)
// .setTitle(R.string.date_picker_title)
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
int year = mDatePicker.getYear();
int month = mDatePicker.getMonth();
int day = mDatePicker.getDayOfMonth();
Date date = new GregorianCalendar(year, month, day).getTime();
sendResult(Activity.RESULT_OK, date);
}
})
.create();
}
警报对话框有一些严格的(奇怪的?)规则来控制它的大小。我不确定如何实际解决它,但有一个解决方法 - 显示对话框后,您可以强制其宽度与日期选择器的宽度相匹配。这为我解决了这个问题,希望它也对你有用:
public Dialog onCreateDialog(Bundle savedInstanceState) { ... final AlertDialog alertDialog = new AlertDialog.Builder(getActivity()) ... .create(); alertDialog.setOnShowListener(new DialogInterface.OnShowListener() { @Override public void onShow(DialogInterface dialog) { WindowManager.LayoutParams lp = new WindowManager.LayoutParams(); final Window window = getDialog().getWindow(); lp.copyFrom(window.getAttributes()); final View picker = window.findViewById(R.id.dialog_date_date_picker); lp.width = picker.getWidth(); lp.height = picker.getHeight(); window.setAttributes(lp); } }); return alertDialog; }
我无法使用 nitzanj 的建议使其工作,但我改变了创建 DatePickerDialog 的方式,它现在按预期工作。完整的来源如下。关键区别在于 onCreateDialog.
public class DatePickerFragment extends DialogFragment
implements DatePickerDialog.OnDateSetListener{
public static final String EXTRA_DATE =
"com.amicly.acaringtext.date";
private static final String ARG_DATE = "date";
@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
Date date = (Date) getArguments().getSerializable(ARG_DATE);
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH);
int day = calendar.get(Calendar.DAY_OF_MONTH);
return new DatePickerDialog(getActivity(), this, year, month, day);
}
public static DatePickerFragment newInstance(Date date) {
Bundle args = new Bundle();
args.putSerializable(ARG_DATE, date);
DatePickerFragment fragment = new DatePickerFragment();
fragment.setArguments(args);
return fragment;
}
private void sendResult(int resultCode, Date date) {
if (getTargetFragment() == null) {
return;
}
Intent intent = new Intent();
intent.putExtra(EXTRA_DATE, date);
getTargetFragment().
onActivityResult(getTargetRequestCode(), resultCode, intent);
}
@Override
public void onDateSet(DatePicker datePicker, int year, int month, int day) {
Date date = new GregorianCalendar(year, month, day).getTime();
sendResult(Activity.RESULT_OK, date);
}
}
如果有人为此苦恼(我肯定是在处理了六个小时之后),那么这可能对你有用。
不要使用带有 DatePicker 的 AlertDialog,而是使用 DatePickerDialog。不仅设置起来更容易,而且实际显示效果如预期。
用法示例:
DateTime dateTime = new DateTime();
new DatePickerDialog(
getActivity(),
R.style.DatePickerDialogCustom,
new DatePickerDialog.OnDateSetListener() {
@Override
public void onDateSet(DatePicker view, int year, int month, int dayOfMonth) {
dateTime = new DateTime(
year,
month + 1,
dayOfMonth,
dateTime.getHourOfDay(),
dateTime.getMinuteOfHour()
);
etDate.setText(dateFormatter.print(dateTime));
}
},
dateTime.getYear(),
dateTime.getMonthOfYear() - 1,
dateTime.getDayOfMonth()
).show();
月份偏移 1,因为 DatePicker returns 月份值介于 0 和 11 之间。
对于样式,请勿使用警告对话框样式。这实际上是导致原始问题的原因。如果不需要自定义样式,只需将其从构造函数中删除(不要使用 null)。如果您使用的是自定义样式,则只需在 styles.xml:
中创建一个新样式<style name="DatePickerDialogCustom" parent="@style/Theme.AppCompat.Dialog">
<item name="android:colorBackground">@color/background</item>
<item name="colorAccent">@color/colorAccent</item>
<item name="android:datePickerStyle">@style/DatePickerCustom</item>
</style>
<style name="DatePickerCustom" parent="@android:style/Widget.Material.DatePicker">
<item name="android:headerBackground">@color/colorAccent</item>
</style>
我不知道同样的问题是否困扰着 TimePickers,但如果是的话,我想类似的解决方案会奏效。
原因是 AlertDialog 比子 DatePicker space 占用更多。
确保使用不带 .Alert
后缀的对话框主题(例如 Theme.AppCompat.Light.Dialog
)。