Creating custom DatePicker dialog

后端 未结 1 1049
温柔的废话
温柔的废话 2021-01-28 06:59

Requirement: When the user clicks on the TextView, a date picker should open up. The default date selected should be the date in the TextView. If the date is in the past, the Da

相关标签:
1条回答
  • 2021-01-28 07:25

    This is a scenario I've already solved and am sharing here in order to help the Xamarin community. The code isn't very optimized, just FYI.

    So, what we exactly need in this scenario is access to the event that the user is changing dates on the DatePicker Dialog. This can only be done if you use a DatePicker inside your own Dialog for more control. In my opinion, you cannot get access to this event if you use the default DatePickerDialog. Thus, we create a dialog extending the DialogFragment class and then implement the DatePicker inside of it. When the user clicks the TextView, we use show the fragment. Let's begin:

    Here's the MainActivity:

    using System;
    using Android.App;
    using Android.Content;
    using Android.Runtime;
    using Android.Views;
    using Android.Widget;
    using Android.OS;
    using Java.Util;
    using Java.Text;
    
    
    namespace DatePickerTest
    {
        [Activity(Label = "DatePickerTest", MainLauncher = true, Icon = "@drawable/icon", Theme = "@android:style/Theme.Holo.Light")]
        public class MainActivity : Activity
        {
            private string dueDate;
    
            private TextView dateLabel;
            private DateTime date;
    
            protected override void OnCreate(Bundle bundle)
            {
                base.OnCreate(bundle);
    
                // Set our view from the "main" layout resource
                SetContentView(Resource.Layout.Main);
    
                dateLabel = (TextView)FindViewById(Resource.Id.dateLabel);
    
                dueDate = dateLabel.Text;
    
                dateLabel.Click += delegate { ShowDialog(); };
    
            }
    
            public void ShowDialog()
            {
                var transaction = FragmentManager.BeginTransaction();
                var dialogFragment = new mDialogFragment();
                dialogFragment.Show(transaction, "dialog_fragment");
            }
    
            //Used for communication with the fragment
            public string GetDueDate()
            {
                return dueDate;
            }
    
            //Used for communication with the fragment
            public void SetDueDate(DateTime date)
            {
             //Additional check so that date isn't set in the past
                if (date < DateTime.Now.Date)
                    Toast.MakeText(this, "Something went wrong! Please try again", ToastLength.Long).Show();
                else
                {
                    SimpleDateFormat MdyFormat = new SimpleDateFormat("MM/dd/yyyy");
                    dueDate = MdyFormat.Format(Date.Parse(date.ToString()));
                    dateLabel.Text = dueDate;
                }
            }
    
        }
    }
    

    Main.axml:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent">
        <Button
            android:id="@+id/MyButton"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:text="@string/Hello" />
        <LinearLayout
            android:orientation="horizontal"
            android:layout_width="fill_parent"
            android:background="#FAFAFA"
            android:layout_height="wrap_content">
            <TextView
                android:id="@+id/dueDateLabel"
                android:layout_height="45dp"
                android:layout_width="wrap_content"
                android:text="Due Date:"
                android:padding="15dp"
                android:textColor="#2E2E2E" />
            <TextView
                android:id="@+id/dateLabel"
                android:layout_height="45dp"
                android:layout_width="fill_parent"
                android:hint="Some Date"
                android:textColor="#2E2E2E"
                android:text="03/16/2015" />
        </LinearLayout>
    </LinearLayout>
    

    MDialogFragment.cs :

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    using Android.App;
    using Android.Content;
    using Android.OS;
    using Android.Runtime;
    using Android.Util;
    using Android.Views;
    using Android.Widget;
    using Java.Util;
    using Java.Text;
    
    namespace DatePickerTest
    {
        public class mDialogFragment : DialogFragment
        {
            DatePicker picker;
            private MainActivity MActivity;
            private int Year, Month, Day;
            private string DueDate;
            private DateTime SelectedDueDate;
            private string tempString = "";
    
            public override void OnCreate(Bundle savedInstanceState)
            {
                base.OnCreate(savedInstanceState);
    
                //Get the instance of the MainActivity
                MActivity = (MainActivity) this.Activity;
    
                //Get the currently set due date
                DueDate = MActivity.GetDueDate();
    
                //Get instance of the Calendar
                Calendar Today = Calendar.Instance;
    
                //Update the class variables
                Year = Today.Get(Calendar.Year);
                Month = Today.Get(Calendar.Month);
                Day = Today.Get(Calendar.Date);
            }
    
            public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
            {
                //Inflating the dialog layout
                var view = inflater.Inflate(Resource.Layout.MDialogLayout, container, false);
                //Finding all the views in it:
                var cancel = (Button)view.FindViewById(Resource.Id.cancel);
                var set = (Button)view.FindViewById(Resource.Id.set);
                picker = (DatePicker)view.FindViewById(Resource.Id.pickerdate);
    
                //DatePicker flag to make it look like the default DatePicker
                picker.CalendarViewShown = false;
    
                //Checking to see if current date is in the past, if YES, disable the 'Set' button
                if ((DateTime.Parse(DueDate) < DateTime.Now)) { set.Enabled = false; }
    
                //Initate the picker with the current due date OR today's date
                picker.Init(GetDefaultYear(), GetDefaultMonth(), GetDefaultDayOfMonth(), new onDateChangedListener((picker1, year, month, day) =>
                {
                    //Getting the DatePicker value in a string
                    tempString = (month + 1) + "/" + day + "/" + year;
    
                    //Parsing the value into a variable
                    SelectedDueDate = (DateTime.Parse(tempString).Date);
    
                    //Setting the MDatePicker dialog's Title
                    Dialog.SetTitle(GetDateDetails(SelectedDueDate));
    
                    //Enable/Disalbe 'Set' button depending on the condition
                    if (SelectedDueDate >= DateTime.Now.Date)
                        set.Enabled = true;
                    else
                        set.Enabled = false;
    
                }));
    
                //Setting Dialog Title for the first time when it opens
                Dialog.SetTitle(GetDateDetails(DateTime.Parse(DueDate)));
    
                //Click function for Cancel button
                cancel.Click += delegate{Dismiss();};
    
                //Click function for Set button
                set.Click += (object sender, EventArgs e) =>
                {
                    SetSelectedDueDate(sender, e);
                };
                return view;
            }
    
            private string GetDateDetails(DateTime date)
            {
                string DateDetails;
                Calendar cal = Calendar.Instance;
                SimpleDateFormat DayOfWeekFormat = new SimpleDateFormat("EEE");
                SimpleDateFormat MonthFormat = new SimpleDateFormat("MMM");
    
                DateDetails = DayOfWeekFormat.Format(Date.Parse(date.ToString())) + ", " + date.Day + " " + MonthFormat.Format(Date.Parse(date.ToString())) + " " + date.Year;
    
                return DateDetails;
            }
    
            private void SetSelectedDueDate(object sender, EventArgs e)
            {
                MActivity.SetDueDate(SelectedDueDate);
                Dismiss();
            }
    
            private int GetDefaultMonth()
            {
                //The currently set due date is in the format "MM/DD/YYYY"
                if(MActivity.GetDueDate()==null || MActivity.GetDueDate() == "")
                    return Month;
    
                return Convert.ToInt32(MActivity.GetDueDate().Substring(0, 2)) - 1;
    
    
            }
    
            private int GetDefaultDayOfMonth()
            {
                if (MActivity.GetDueDate() == null || MActivity.GetDueDate() == "")
                    return Day;
                return Convert.ToInt32(MActivity.GetDueDate().Substring(3, 2)); 
            }
    
            private int GetDefaultYear()
            {
                if (MActivity.GetDueDate() == null || MActivity.GetDueDate() == "")
                    return Year;
                return Convert.ToInt32(MActivity.GetDueDate().Substring(6, 4));
            }
        }
    
        //We need this class and interface implementation to create and Init the DatePicker
        class onDateChangedListener : Java.Lang.Object, DatePicker.IOnDateChangedListener
        {
    
            Action<DatePicker, int, int, int> callback;
    
            public onDateChangedListener(Action<DatePicker, int, int, int> callback)
            {
                this.callback = callback;
            }
    
            public void OnDateChanged(DatePicker view, int year, int monthOfYear, int dayOfMonth)
            {
                callback(view, year, monthOfYear, dayOfMonth);
            }
        }
    }
    

    MDialogLayout.axml :

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content">
    
        <DatePicker
            android:id="@+id/pickerdate"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal" />
        <LinearLayout
            android:orientation="horizontal"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content">
            <Button
                android:id="@+id/cancel"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Cancel"
                android:layout_weight="1"
                style="?android:attr/buttonBarButtonStyle" />
            <Button
                android:id="@+id/set"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="SET"
                android:layout_weight="1"
                style="?android:attr/buttonBarButtonStyle"
                android:paddingTop="1dp" />
        </LinearLayout>
    </LinearLayout>
    
    0 讨论(0)
提交回复
热议问题