xamarin 如何设置DatePicker仅显示月份和年份

v9tzhpje  于 2022-12-07  发布在  其他
关注(0)|答案(1)|浏览(133)

我编码xamarin移动的应用程序,我使用DatePicker它的显示日期年和月,但我想设置DatePicker只显示月和年如何设置对不起我的英语

<DatePicker
    IsVisible="False"
    x:Name="monthpick"
    Style="{StaticResource styLabel_Small}"
    VerticalOptions="FillAndExpand"
    HorizontalOptions="FillAndExpand" />

我想知道如何设置datepicker只显示月份和年份

xam8gpfp

xam8gpfp1#

您可以使用Xamarin.Forms Custom Renderers来制作DatePicker。
首先,您需要创建一个自定义视图。

using System;
using System.Collections.Generic;
using System.Text;
using Xamarin.Forms;

namespace App53
{
    public  class MonthYearPickerView :View
    {
      
        public static readonly BindableProperty FontSizeProperty = BindableProperty.Create(
            propertyName: nameof(FontSize),
            returnType: typeof(double),
            declaringType: typeof(MonthYearPickerView),
            defaultValue: (double)24,
            defaultBindingMode: BindingMode.TwoWay);

        [TypeConverter(typeof(FontSizeConverter))]
        public double FontSize
        {
            get => (double)GetValue(FontSizeProperty);
            set => SetValue(FontSizeProperty, value);
        }

       

        public static readonly BindableProperty TextColorProperty = BindableProperty.Create(
            propertyName: nameof(TextColor),
            returnType: typeof(Color),
            declaringType: typeof(MonthYearPickerView),
            defaultValue: Color.White,
            defaultBindingMode: BindingMode.TwoWay);

        public Color TextColor
        {
            get => (Color)GetValue(TextColorProperty);
            set => SetValue(TextColorProperty, value);
        }

     
        public static readonly BindableProperty InfiniteScrollProperty = BindableProperty.Create(
            propertyName: nameof(InfiniteScroll),
            returnType: typeof(bool),
            declaringType: typeof(MonthYearPickerView),
            defaultValue: true,
            defaultBindingMode: BindingMode.TwoWay);

        public bool InfiniteScroll
        {
            get => (bool)GetValue(InfiniteScrollProperty);
            set => SetValue(InfiniteScrollProperty, value);
        }

  

        public static readonly BindableProperty DateProperty = BindableProperty.Create(
            propertyName: nameof(Date),
            returnType: typeof(DateTime),
            declaringType: typeof(MonthYearPickerView),
            defaultValue: default,
            defaultBindingMode: BindingMode.TwoWay);

        public DateTime Date
        {
            get => (DateTime)GetValue(DateProperty);
            set => SetValue(DateProperty, value);
        }


        public static readonly BindableProperty MaxDateProperty = BindableProperty.Create(
            propertyName: nameof(MaxDate),
            returnType: typeof(DateTime?),
            declaringType: typeof(MonthYearPickerView),
            defaultValue: default,
            defaultBindingMode: BindingMode.TwoWay);

        public DateTime? MaxDate
        {
            get => (DateTime?)GetValue(MaxDateProperty);
            set => SetValue(MaxDateProperty, value);
        }


        public static readonly BindableProperty MinDateProperty = BindableProperty.Create(
            propertyName: nameof(MinDate),
            returnType: typeof(DateTime?),
            declaringType: typeof(MonthYearPickerView),
            defaultValue: default,
            defaultBindingMode: BindingMode.TwoWay);

        public DateTime? MinDate
        {
            get => (DateTime?)GetValue(MinDateProperty);
            set => SetValue(MinDateProperty, value);
        }

      
    }
}

其次,您需要更改Android项目文件夹中的代码。
在主活动中:

public static MainActivity Instance { get; private set; }

    protected override void OnCreate(Bundle savedInstanceState)
    {
        TabLayoutResource = Resource.Layout.Tabbar;
        ToolbarResource = Resource.Layout.Toolbar;

        Instance = this;

        base.OnCreate(savedInstanceState);

        Xamarin.Essentials.Platform.Init(this, savedInstanceState);
        global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
        LoadApplication(new App());
    }

创建一个名为MonthYearPickerRenderer的类:

using Android.Content;
using Android.Support.V7.App;
using Android.Widget;
using App53;
using App53.Droid;
using System;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;

[assembly: ExportRenderer(typeof(MonthYearPickerView), typeof(MonthYearPickerRenderer))]
namespace App53.Droid
{
    public class MonthYearPickerRenderer : ViewRenderer<MonthYearPickerView, EditText>
    {
        private readonly Context _context;
        private MonthYearPickerDialog _monthYearPickerDialog;

        public MonthYearPickerRenderer(Context context) : base(context)
        {
            _context = context;
        }

        protected override void OnElementChanged(ElementChangedEventArgs<MonthYearPickerView> e)
        {
            base.OnElementChanged(e);

            CreateAndSetNativeControl();

            Control.KeyListener = null;
            Element.Focused += Element_Focused;
        }

        protected override void Dispose(bool disposing)
        {
            if (Control == null) return;

            Element.Focused -= Element_Focused;

            if (_monthYearPickerDialog != null)
            {
                _monthYearPickerDialog.OnDateTimeChanged -= OnDateTimeChanged;
                _monthYearPickerDialog.OnClosed -= OnClosed;
                _monthYearPickerDialog.Hide();
                _monthYearPickerDialog.Dispose();
                _monthYearPickerDialog = null;
            }

            base.Dispose(disposing);
        }

        #region Private Methods

        private void ShowDatePicker()
        {
            if (_monthYearPickerDialog == null)
            {
                _monthYearPickerDialog = new MonthYearPickerDialog();
                _monthYearPickerDialog.OnDateTimeChanged += OnDateTimeChanged;
                _monthYearPickerDialog.OnClosed += OnClosed;
            }
            _monthYearPickerDialog.Date = Element.Date;
            _monthYearPickerDialog.MinDate = FormatDateToMonthYear(Element.MinDate);
            _monthYearPickerDialog.MaxDate = FormatDateToMonthYear(Element.MaxDate);
            _monthYearPickerDialog.InfiniteScroll = Element.InfiniteScroll;

            var appcompatActivity = MainActivity.Instance;
            var mFragManager = appcompatActivity?.SupportFragmentManager;
            if (mFragManager != null)
            {
                _monthYearPickerDialog.Show(mFragManager, nameof(MonthYearPickerDialog));
            }
        }

        private void ClearPickerFocus()
        {
            ((IElementController)Element).SetValueFromRenderer(VisualElement.IsFocusedProperty, false);
            Control.ClearFocus();
        }

        private DateTime? FormatDateToMonthYear(DateTime? dateTime) => 
            dateTime.HasValue ? (DateTime?) new DateTime(dateTime.Value.Year, dateTime.Value.Month, 1) : null;

        private void CreateAndSetNativeControl()
        {
            var tv = new EditText(_context);

            tv.SetTextColor(Element.TextColor.ToAndroid());
            tv.TextSize = (float)Element.FontSize;
            tv.Text = $"{Element.Date.Month:D2} | {Element.Date.Year}";
            tv.Gravity = Android.Views.GravityFlags.Center;
            tv.SetBackgroundColor(Element.BackgroundColor.ToAndroid());

            SetNativeControl(tv);
        }

        #endregion

        #region Event Handlers

        private void Element_Focused(object sender, FocusEventArgs e)
        {
            if (e.IsFocused)
            {
                ShowDatePicker();
            }
        }

        private void OnClosed(object sender, DateTime e)
        {
            ClearPickerFocus();
        }

        private void OnDateTimeChanged(object sender, DateTime e)
        {
            Element.Date = e;
            Control.Text = $"{Element.Date.Month:D2} | {Element.Date.Year}";
            ClearPickerFocus();
        }

        #endregion
    }
}

创建一个类MonthYearPickerDialog:

using Android.App;
    using Android.OS;
    using Android.Views;
    using Android.Widget;
    using System;
    using System.Linq;
    
    
    namespace App53.Droid
    {
        public class MonthYearPickerDialog : Android.Support.V4.App.DialogFragment
        {
            public event EventHandler<DateTime> OnDateTimeChanged;
            public event EventHandler<DateTime> OnClosed;
    
            #region Private Fields
    
            private const int DefaultDay = 1;
            private const int MinNumberOfMonths = 1;
            private const int MaxNumberOfMonths = 12;
            private const int MinNumberOfYears = 1900;
            private const int MaxNumberOfYears = 2100;
    
            private NumberPicker _monthPicker;
            private NumberPicker _yearPicker;
    
            #endregion
    
            #region Public Properties
            
            public DateTime? MinDate { get; set; }
            public DateTime? MaxDate { get; set; }
            public DateTime? Date { get; set; }
            public bool InfiniteScroll { get; set; }
    
            #endregion
    
            public void Hide() => base.Dialog?.Hide();
    
            public override Dialog OnCreateDialog(Bundle savedInstanceState)
            {
                var builder = new AlertDialog.Builder(Activity);
                var inflater = Activity.LayoutInflater;
    
                var selectedDate = GetSelectedDate();
    
                var dialog = inflater.Inflate(Resource.Layout.date_picker_dialog, null);
                _monthPicker = (NumberPicker)dialog.FindViewById(Resource.Id.picker_month);
                _yearPicker = (NumberPicker)dialog.FindViewById(Resource.Id.picker_year);
    
                InitializeMonthPicker(selectedDate.Month);
                InitializeYearPicker(selectedDate.Year);
                SetMaxMinDate(MaxDate, MinDate);
    
                builder.SetView(dialog)
                    .SetPositiveButton("Ok", (sender, e) =>
                    {
                        selectedDate = new DateTime(_yearPicker.Value, _monthPicker.Value, DefaultDay);
                        OnDateTimeChanged?.Invoke(dialog, selectedDate);
                    })
                    .SetNegativeButton("Cancel", (sender, e) =>
                    {
                        Dialog.Cancel();
                        OnClosed?.Invoke(dialog, selectedDate);
                    });
                return builder.Create();
            }
    
            protected override void Dispose(bool disposing)
            {
                if (_yearPicker != null)
                {
                    _yearPicker.ScrollChange -= YearPicker_ScrollChange;
                    _yearPicker.Dispose();
                    _yearPicker = null;
                }
    
                _monthPicker?.Dispose();
                _monthPicker = null;
    
    
                base.Dispose(disposing);
            }
    
            #region Private Methods
    
            private DateTime GetSelectedDate() => Date ?? DateTime.Now;
    
            private void InitializeYearPicker(int year)
            {
                _yearPicker.MinValue = MinNumberOfYears;
                _yearPicker.MaxValue = MaxNumberOfYears;
                _yearPicker.Value = year;
                _yearPicker.ScrollChange += YearPicker_ScrollChange;
                if (!InfiniteScroll)
                {
                    _yearPicker.WrapSelectorWheel = false;
                    _yearPicker.DescendantFocusability = DescendantFocusability.BlockDescendants;
                }
            }
    
            private void InitializeMonthPicker(int month)
            {
                _monthPicker.MinValue = MinNumberOfMonths;
                _monthPicker.MaxValue = MaxNumberOfMonths;
                _monthPicker.SetDisplayedValues(GetMonthNames());
                _monthPicker.Value = month;
                if (!InfiniteScroll)
                {
                    _monthPicker.WrapSelectorWheel = false;
                    _monthPicker.DescendantFocusability = DescendantFocusability.BlockDescendants;
                }
            }
    
            private void YearPicker_ScrollChange(object sender, View.ScrollChangeEventArgs e)
            {
                SetMaxMinDate(MaxDate, MinDate);
            }
    
            private void SetMaxMinDate(DateTime? maxDate, DateTime? minDate)
            {
                try
                {
                    if (maxDate.HasValue)
                    {
                        var maxYear = maxDate.Value.Year;
                        var maxMonth = maxDate.Value.Month;
    
                        if (_yearPicker.Value == maxYear)
                        {
                            _monthPicker.MaxValue = maxMonth;
                        }
                        else if (_monthPicker.MaxValue != MaxNumberOfMonths)
                        {
                            _monthPicker.MaxValue = MaxNumberOfMonths;
                        }
    
                        _yearPicker.MaxValue = maxYear;
                    }
    
                    if (minDate.HasValue)
                    {
                        var minYear = minDate.Value.Year;
                        var minMonth = minDate.Value.Month;
    
                        if (_yearPicker.Value == minYear)
                        {
                            _monthPicker.MinValue = minMonth;
                        }
                        else if (_monthPicker.MinValue != MinNumberOfMonths)
                        {
                            _monthPicker.MinValue = MinNumberOfMonths;
                        }
    
                        _yearPicker.MinValue = minYear;
                    }
                    _monthPicker.SetDisplayedValues(GetMonthNames(_monthPicker.MinValue));
                }
                catch (Exception e)
                {
                  
                }
            }
    
            private string[] GetMonthNames(int start = 1) => 
                System.Globalization.DateTimeFormatInfo.CurrentInfo?.MonthNames.Skip(start - 1).ToArray();
    
            #endregion
    
        }
    }

在资源-〉布局中创建date_picker_dialog.xml:

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="vertical">

  <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:orientation="horizontal">

    <NumberPicker
            android:id="@+id/picker_month"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginEnd="15dp"
            android:layout_marginRight="15dp">
    </NumberPicker>

    <NumberPicker
            android:id="@+id/picker_year"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content">
    </NumberPicker>
  </LinearLayout>
</LinearLayout>

最后,您可以在xaml中使用MonthYearPickerView

<StackLayout VerticalOptions="CenterAndExpand" HorizontalOptions="CenterAndExpand">
        <local:MonthYearPickerView
            Date="12.06.2022"
            BackgroundColor="Red"
            HorizontalOptions="CenterAndExpand"
            VerticalOptions="Center" />
</StackLayout>

相关问题