要求:当用户点击TextView时,应打开日期选择器。选择的默认日期应为TextView中的日期。如果日期是过去的日期,则应禁用DatePicker对话框的“设置”按钮。如果可单击的TextView为空,则DatePicker中的默认日期应为今天的日期。
答案 0 :(得分:1)
这是我已经解决并在此分享的方案,以帮助Xamarin社区。代码没有经过优化,仅供参考。
因此,在这种情况下我们真正需要的是访问用户正在更改DatePicker对话框上的日期的事件。只有在自己的Dialog中使用DatePicker才能进行更多控制时,才能执行此操作。在我看来,如果使用默认的DatePickerDialog,则无法访问此事件。因此,我们创建一个扩展DialogFragment类的对话框,然后在其中实现DatePicker。当用户单击TextView时,我们使用show the fragment。让我们开始吧:
这是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>