DatePicker小部件在Nexus 6上未占据整个AlertDialog

9
我有一个DatePickerFragment,它使用一个非常简单的自定义布局。在较小的设备上(HTC One m7),该布局占用整个警告对话框,但在Nexus 6上不占用整个宽度。有人知道为什么DatePicker没有占满Nexus 6警告对话框的整个宽度或从哪里开始进行故障排除吗?谢谢!
Nexus 6(请注意,日期标题未填充整个警告对话框)

enter image description here

HTC One m7

enter image description here

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();
        }

你解决过这个问题吗? - Nico
我已经没有 Nexus 6 来测试了,但我已经更改了 dialog_date.xml 文件,将 android:layout_width="match_parent"。 - dazza5000
我尝试过这样做,但似乎没有帮助。我将我的6p手机的dpi设置得比默认值更高,但在UI预览中也是这样显示的。而且横屏模式下一切正常。 - Nico
请验证您是否有不同分辨率的多个布局文件。将match_parent用作DatePicker的layout_width和layout_height。最后,查看DatePickerFragment的布局,并验证那里没有填充/边距。 - Clint Deygoo
1
@clint 我可以确认我只有一个布局,甚至在布局编辑器中也是这样显示的。有趣的是,我有一个时间选择器设置完全相同,它适合得很好。 - Nico
显示剩余2条评论
4个回答

13

原因是AlertDialog所占用的空间比子类DatePicker多。

请确保使用对话框主题(例如Theme.AppCompat.Light.Dialog),不要加上.Alert后缀。


感谢您提供这么简短明了的信息,真是太棒了。 :) - Subhan Ali

4

警告对话框有一些严格(奇怪?)的规则来控制其大小。我不确定如何实际解决它,但有一个解决方法 - 一旦显示对话框,您可以强制其宽度与日期选择器的宽度匹配。这为我解决了问题,希望对您也有用:

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;
}

太好了,谢谢!但愿我知道为什么它不能正常适配,但这个解决方案完全可行,再次感谢 :) - Nico
这对我没有起作用。仍在尝试寻找解决方案。干杯! - dazza5000
@dazza5000 使用 android.app.AlertDialog 是非常重要的,不要使用 android.support.v7.app.AlertDialog - Paul Woitaschek
final Window window = *getDialog()*.getWindow(); 这个选项在我的选项中没有提供/显示。 - RoCkDevstack

1
如果有人对此感到困惑(我在处理了六个小时后肯定是这样),那么这可能适用于您。不要使用AlertDialog和其中的DatePicker,而是使用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返回的月份值在0到11之间。
对于样式,请不要使用Alert Dialog样式。这实际上是导致原始问题的原因。如果您不需要自定义样式,请从构造函数中删除它(不要使用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是否存在同样的问题,但如果存在,我想类似的解决方案将会起作用。

-1

我无法使用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);
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接