如何将自定义按钮添加到 material 日期范围选择器 android?

How to add custom button to material date range picker android?

如何向 material 日期范围选择器添加自定义按钮?

我正在尝试获取对话框的视图,以便我可以通过编程方式添加按钮,但我无法从选择器中获取任何视图。

        MaterialDatePicker.Builder<Pair<Long,Long>> builder = MaterialDatePicker.Builder.dateRangePicker();
        MaterialDatePicker<Pair<Long,Long>> materialDatePicker = builder
            .setTitleText("Select Dates")
            .build();
        dateRangeTV.setOnClickListener(v -> {
            materialDatePicker.show(getSupportFragmentManager(), "DATE_PICKER");
            View root = materialDatePicker.requireView();
        });

但是我说的是错误的。

java.lang.IllegalStateException: Fragment MaterialDatePicker{e52ecfc} (40593b4f-a55a-4d6c-aa3b-2b778e721149 tag=DATE_PICKER) did not return a View from onCreateView() or this was called before onCreateView().

在这个例子中,我创建了一个 class MainActivity.java,它的布局从 Button 打开自定义对话框,如下所示:

MainActivity.java:

public class MainActivity extends AppCompatActivity {

    private static final String TAG = "MainActivity";

    private Button openDialog;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        openDialog = findViewById(R.id.open_dialog);
        openDialog.setOnClickListener(v -> {
            Log.d(TAG, "onClick: opening dialog.");
            MyCustomDialog dialog = new MyCustomDialog();
            dialog.show(getSupportFragmentManager(), "MyCustomDialog");
        });
    }
}

LayoutButton activity_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="MainActivity">

    <Button
        android:id="@+id/open_dialog"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="20sp"
        android:text="open dialog" />

</RelativeLayout>

并且 MyCustomDialog.java class 扩展了 DialogFragment 以具有自定义视图来存储 DatePicker 以及其中的其他 Widgets。 (例如 TextView):

public class MyCustomDialog extends DialogFragment {

    private static final String TAG = "MyCustomDialog";

    private TextView mActionOk, mActionCancel;

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.dialog_my_custom, container, false);
        mActionCancel = view.findViewById(R.id.action_cancel);
        mActionOk = view.findViewById(R.id.action_ok);

        mActionCancel.setOnClickListener(v -> {
            Log.d(TAG, "onClick: closing dialog");
            getDialog().dismiss();
        });

        mActionOk.setOnClickListener(v -> {
            Log.d(TAG, "onClick: capturing input");
            getDialog().dismiss();
        });

        return view;
    }
}

最后但并非最不重要的 XML 文件 dialog_my_custom.xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="550dp"
        android:padding="10dp">

        <TextView
            android:id="@+id/heading"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginBottom="20dp"
            android:text="This is your custom View with DatePicker"
            android:textAlignment="center"
            android:textColor="#000"
            android:textSize="18sp" />

        <DatePicker
            android:id="@+id/date_picker"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@+id/heading"
            android:layout_centerHorizontal="true" />

        <RelativeLayout
            android:id="@+id/frame"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@+id/date_picker">

            <TextView
                android:id="@+id/action_ok"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentRight="true"
                android:layout_alignParentBottom="true"
                android:layout_marginRight="20dp"
                android:text="OK"
                android:textColor="#33bbff"
                android:textSize="18sp" />

            <TextView
                android:id="@+id/action_cancel"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentLeft="true"
                android:layout_alignParentBottom="true"
                android:layout_marginRight="20dp"
                android:text="CANCEL"
                android:textColor="#33bbff"
                android:textSize="18sp" />
        </RelativeLayout>
    </RelativeLayout>
</RelativeLayout>

不要忘记添加支持库的dependency

implementation  "com.android.support:appcompat-v7:$supportLibVersion"

结果:

发生此错误是因为 materialDatePicker.show() 是异步调用,并且 MaterialDatePicker (DialogFragment) 尚未创建,无法访问其根视图。为避免此错误,您必须通过添加 DefaultLifecycleObserver 使用 materialDatePicker.getLifecycle() 侦听 DialogFragment Lifecycle 并使用覆盖方法 void onStart(@NonNull LifecycleOwner owner) 访问 MaterialDatePicker 根从那里查看。

将您的代码更改为如下所示:

MaterialDatePicker.Builder<Pair<Long,Long>> builder = MaterialDatePicker.Builder.dateRangePicker();
MaterialDatePicker<Pair<Long,Long>> materialDatePicker = builder
        .setTitleText("Select Dates")
        .build();
materialDatePicker.getLifecycle().addObserver(new DefaultLifecycleObserver()
{
    @Override
    public void onCreate(@NonNull LifecycleOwner owner) {}

    @Override
    public void onStart(@NonNull LifecycleOwner owner) {
        //in onStart of DialogFragment the View has been created so you can access the materialDatePicker.requireView()
        View root = materialDatePicker.requireView();
        //from root find the View you are interested to add your custom button
    }

    @Override
    public void onResume(@NonNull LifecycleOwner owner) {}

    @Override
    public void onDestroy(@NonNull LifecycleOwner owner) {
        //remove Lifecycle Observer
        materialDatePicker.getLifecycle().removeObserver(this);
    }
});
materialDatePicker.show(getSupportFragmentManager(), "DATE_PICKER");