From 3b1c58382352cf0719e7a8060049d72bc688abf0 Mon Sep 17 00:00:00 2001 From: Vladislav Antonyuk Date: Sun, 24 Dec 2023 04:35:00 +0200 Subject: [PATCH] MaterialCalendarView --- .../Directory.Build.props | 10 ++ .../Additions/AboutAdditions.txt | 48 +++++++++ .../MaterialCalendarView.csproj | 50 ++++++++++ .../MaterialCalendarView/ReadMe.md | 3 + .../Transforms/EnumFields.xml | 14 +++ .../Transforms/EnumMethods.xml | 13 +++ .../Transforms/Metadata.xml | 9 ++ MauiBells/MauiBells.csproj | 7 +- MauiBells/MauiProgram.cs | 6 +- .../Android/CalendarMaterialHandler.cs | 99 +++++++++++++++++++ MauiSamples.sln | 15 ++- NuGet.config | 2 +- 12 files changed, 270 insertions(+), 6 deletions(-) create mode 100644 AndroidBindableLibraries/Directory.Build.props create mode 100644 AndroidBindableLibraries/MaterialCalendarView/Additions/AboutAdditions.txt create mode 100644 AndroidBindableLibraries/MaterialCalendarView/MaterialCalendarView.csproj create mode 100644 AndroidBindableLibraries/MaterialCalendarView/ReadMe.md create mode 100644 AndroidBindableLibraries/MaterialCalendarView/Transforms/EnumFields.xml create mode 100644 AndroidBindableLibraries/MaterialCalendarView/Transforms/EnumMethods.xml create mode 100644 AndroidBindableLibraries/MaterialCalendarView/Transforms/Metadata.xml create mode 100644 MauiBells/Platforms/Android/CalendarMaterialHandler.cs diff --git a/AndroidBindableLibraries/Directory.Build.props b/AndroidBindableLibraries/Directory.Build.props new file mode 100644 index 00000000..1ef3cd4d --- /dev/null +++ b/AndroidBindableLibraries/Directory.Build.props @@ -0,0 +1,10 @@ + + + + net8.0-android + enable + enable + true + false + + \ No newline at end of file diff --git a/AndroidBindableLibraries/MaterialCalendarView/Additions/AboutAdditions.txt b/AndroidBindableLibraries/MaterialCalendarView/Additions/AboutAdditions.txt new file mode 100644 index 00000000..2775bd36 --- /dev/null +++ b/AndroidBindableLibraries/MaterialCalendarView/Additions/AboutAdditions.txt @@ -0,0 +1,48 @@ +Additions allow you to add arbitrary C# to the generated classes +before they are compiled. This can be helpful for providing convenience +methods or adding pure C# classes. + +== Adding Methods to Generated Classes == + +Let's say the library being bound has a Rectangle class with a constructor +that takes an x and y position, and a width and length size. It will look like +this: + +public partial class Rectangle +{ + public Rectangle (int x, int y, int width, int height) + { + // JNI bindings + } +} + +Imagine we want to add a constructor to this class that takes a Point and +Size structure instead of 4 ints. We can add a new file called Rectangle.cs +with a partial class containing our new method: + +public partial class Rectangle +{ + public Rectangle (Point location, Size size) : + this (location.X, location.Y, size.Width, size.Height) + { + } +} + +At compile time, the additions class will be added to the generated class +and the final assembly will a Rectangle class with both constructors. + + +== Adding C# Classes == + +Another thing that can be done is adding fully C# managed classes to the +generated library. In the above example, let's assume that there isn't a +Point class available in Java or our library. The one we create doesn't need +to interact with Java, so we'll create it like a normal class in C#. + +By adding a Point.cs file with this class, it will end up in the binding library: + +public class Point +{ + public int X { get; set; } + public int Y { get; set; } +} \ No newline at end of file diff --git a/AndroidBindableLibraries/MaterialCalendarView/MaterialCalendarView.csproj b/AndroidBindableLibraries/MaterialCalendarView/MaterialCalendarView.csproj new file mode 100644 index 00000000..eedbde30 --- /dev/null +++ b/AndroidBindableLibraries/MaterialCalendarView/MaterialCalendarView.csproj @@ -0,0 +1,50 @@ + + + 23 + VladislavAntonyuk.$(AssemblyName) + 1.9.0 + ReadMe.md + ..\..\LocalPackages\ + + + + + + + + + + + + + 1.6.1.6 + + + 2.1.4.9 + + + 1.12.0.3 + + + 1.9.21.1 + + + 1.9.21.1 + + + + + + + + + 1.6.2.1 + + + + + True + \ + + + \ No newline at end of file diff --git a/AndroidBindableLibraries/MaterialCalendarView/ReadMe.md b/AndroidBindableLibraries/MaterialCalendarView/ReadMe.md new file mode 100644 index 00000000..3daea972 --- /dev/null +++ b/AndroidBindableLibraries/MaterialCalendarView/ReadMe.md @@ -0,0 +1,3 @@ +# Android Material Calendar View + +Android Java Library Binding for [Material Calendar View](https://github.com/Applandeo/Material-Calendar-View) \ No newline at end of file diff --git a/AndroidBindableLibraries/MaterialCalendarView/Transforms/EnumFields.xml b/AndroidBindableLibraries/MaterialCalendarView/Transforms/EnumFields.xml new file mode 100644 index 00000000..22959957 --- /dev/null +++ b/AndroidBindableLibraries/MaterialCalendarView/Transforms/EnumFields.xml @@ -0,0 +1,14 @@ + + + \ No newline at end of file diff --git a/AndroidBindableLibraries/MaterialCalendarView/Transforms/EnumMethods.xml b/AndroidBindableLibraries/MaterialCalendarView/Transforms/EnumMethods.xml new file mode 100644 index 00000000..49216c61 --- /dev/null +++ b/AndroidBindableLibraries/MaterialCalendarView/Transforms/EnumMethods.xml @@ -0,0 +1,13 @@ + + + \ No newline at end of file diff --git a/AndroidBindableLibraries/MaterialCalendarView/Transforms/Metadata.xml b/AndroidBindableLibraries/MaterialCalendarView/Transforms/Metadata.xml new file mode 100644 index 00000000..91493a25 --- /dev/null +++ b/AndroidBindableLibraries/MaterialCalendarView/Transforms/Metadata.xml @@ -0,0 +1,9 @@ + + + diff --git a/MauiBells/MauiBells.csproj b/MauiBells/MauiBells.csproj index 449862ce..e4e7a78b 100644 --- a/MauiBells/MauiBells.csproj +++ b/MauiBells/MauiBells.csproj @@ -29,7 +29,12 @@ + - + + + + + diff --git a/MauiBells/MauiProgram.cs b/MauiBells/MauiProgram.cs index 72ce8598..7fbc2369 100644 --- a/MauiBells/MauiProgram.cs +++ b/MauiBells/MauiProgram.cs @@ -10,7 +10,11 @@ public static MauiApp CreateMauiApp() builder.UseMauiApp() .ConfigureMauiHandlers(handlers => { - handlers.AddHandler(); +#if ANDROID + handlers.AddHandler(); +#else + handlers.AddHandler(); +#endif }); return builder.Build(); diff --git a/MauiBells/Platforms/Android/CalendarMaterialHandler.cs b/MauiBells/Platforms/Android/CalendarMaterialHandler.cs new file mode 100644 index 00000000..3ec57e25 --- /dev/null +++ b/MauiBells/Platforms/Android/CalendarMaterialHandler.cs @@ -0,0 +1,99 @@ +namespace MauiBells.Calendar; + +using System.ComponentModel; +using Android; +using Com.Applandeo.Materialcalendarview; +using Com.Applandeo.Materialcalendarview.Listeners; +using Java.Lang; +using Microsoft.Maui.Handlers; +using Calendar = Com.Applandeo.Materialcalendarview.CalendarView; + +public class CalendarMaterialHandler(IPropertyMapper mapper, CommandMapper? commandMapper = null) : ViewHandler(mapper, commandMapper) +{ + public static IPropertyMapper PropertyMapper = new PropertyMapper(ViewMapper) + { + [nameof(ICalendarView.FirstDayOfWeek)] = MapFirstDayOfWeek, + [nameof(ICalendarView.MinDate)] = MapMinDate, + [nameof(ICalendarView.MaxDate)] = MapMaxDate, + [nameof(ICalendarView.SelectedDate)] = MapSelectedDate, + }; + + public static CommandMapper CommandMapper = new(ViewCommandMapper); + + public CalendarMaterialHandler() : this(PropertyMapper, CommandMapper) + { + } + + protected override Calendar CreatePlatformView() + { + return new Calendar(Context); + } + + protected override void ConnectHandler(Calendar platformView) + { + base.ConnectHandler(platformView); + platformView.CalendarDayClick += PlatformView_SelectedDatesChanged; + } + + private void PlatformView_SelectedDatesChanged(object? sender, CalendarDayClickEventArgs e) + { + var calendar = e.CalendarDay.Calendar; + var time = TimeSpan.FromMilliseconds(calendar.TimeInMillis); + var result = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); + VirtualView.SelectedDate = new DateTimeOffset(result.Add(time).Add(TimeSpan.FromMilliseconds(calendar.TimeZone.RawOffset))); + VirtualView.OnSelectedDateChanged(VirtualView.SelectedDate); + } + + protected override void DisconnectHandler(Calendar platformView) + { + platformView.CalendarDayClick -= PlatformView_SelectedDatesChanged; + base.DisconnectHandler(platformView); + } + + private static void MapFirstDayOfWeek(CalendarMaterialHandler handler, ICalendarView virtualView) + { + var calendarWeekDate = virtualView.FirstDayOfWeek switch + { + DayOfWeek.Sunday => CalendarWeekDay.Sunday, + DayOfWeek.Monday => CalendarWeekDay.Monday, + DayOfWeek.Tuesday => CalendarWeekDay.Tuesday, + DayOfWeek.Wednesday => CalendarWeekDay.Wednesday, + DayOfWeek.Thursday => CalendarWeekDay.Thursday, + DayOfWeek.Friday => CalendarWeekDay.Friday, + DayOfWeek.Saturday => CalendarWeekDay.Saturday, + _ => throw new InvalidEnumArgumentException(), + }; + ArgumentNullException.ThrowIfNull(calendarWeekDate); + handler.PlatformView.SetFirstDayOfWeek(calendarWeekDate); + } + + private static void MapMinDate(CalendarMaterialHandler handler, ICalendarView virtualView) + { + var calendar = Java.Util.Calendar.Instance; + calendar.Set(virtualView.MinDate.Year, virtualView.MinDate.Month - 1, virtualView.MinDate.Day); + handler.PlatformView.SetMinimumDate(calendar); + } + + private static void MapMaxDate(CalendarMaterialHandler handler, ICalendarView virtualView) + { + var calendar = Java.Util.Calendar.Instance; + calendar.Set(virtualView.MaxDate.Year, virtualView.MaxDate.Month - 1, virtualView.MaxDate.Day); + handler.PlatformView.SetMaximumDate(calendar); + } + + private static void MapSelectedDate(CalendarMaterialHandler handler, ICalendarView virtualView) + { + if (virtualView.SelectedDate is null) + { + return; + } + + var calendar = Java.Util.Calendar.Instance; + calendar.Set(virtualView.SelectedDate.Value.Year, virtualView.SelectedDate.Value.Month - 1, virtualView.SelectedDate.Value.Day); + List events = new(); + var day = new CalendarDay(calendar); + day.BackgroundResource = Integer.ValueOf(Resource.Color.HoloRedDark); + events.Add(day); + handler.PlatformView.SetCalendarDays(events); + } +} \ No newline at end of file diff --git a/MauiSamples.sln b/MauiSamples.sln index f55924f7..4c963857 100644 --- a/MauiSamples.sln +++ b/MauiSamples.sln @@ -54,9 +54,6 @@ EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BottomSheet", "BottomSheet\BottomSheet.csproj", "{29FEFF3E-62BD-4156-993A-7264EC281AA9}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "iOSExtensions", "iOSExtensions", "{F215B6A7-4C79-4415-95D2-6F561143C9AC}" - ProjectSection(SolutionItems) = preProject - iOSExtensions\Directory.Build.props = iOSExtensions\Directory.Build.props - EndProjectSection EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AppContainer", "iOSExtensions\ShareExtension\AppContainer\AppContainer.csproj", "{E3B8C927-987B-410C-9B8F-9C683B2F494A}" EndProject @@ -126,6 +123,13 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Database", "Database", "{D3 EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MauiTaskListApp", "Database\MauiTaskListApp\MauiTaskListApp.csproj", "{08096F4C-2BB3-4860-B0CA-9EC6A09EC377}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "AndroidBindableLibraries", "AndroidBindableLibraries", "{E08722A6-C1B6-4C83-983C-809BF721D6F1}" + ProjectSection(SolutionItems) = preProject + AndroidBindableLibraries\Directory.Build.props = AndroidBindableLibraries\Directory.Build.props + EndProjectSection +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MaterialCalendarView", "AndroidBindableLibraries\MaterialCalendarView\MaterialCalendarView.csproj", "{42DD8662-FBD2-47B8-8740-17807E17EF5A}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -372,6 +376,10 @@ Global {08096F4C-2BB3-4860-B0CA-9EC6A09EC377}.Release|Any CPU.ActiveCfg = Release|Any CPU {08096F4C-2BB3-4860-B0CA-9EC6A09EC377}.Release|Any CPU.Build.0 = Release|Any CPU {08096F4C-2BB3-4860-B0CA-9EC6A09EC377}.Release|Any CPU.Deploy.0 = Release|Any CPU + {42DD8662-FBD2-47B8-8740-17807E17EF5A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {42DD8662-FBD2-47B8-8740-17807E17EF5A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {42DD8662-FBD2-47B8-8740-17807E17EF5A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {42DD8662-FBD2-47B8-8740-17807E17EF5A}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -392,6 +400,7 @@ Global {8CE62F62-CE5D-48F4-8754-3F07FF72C3C2} = {D7258BEF-416D-4F3E-A359-87BD545A84A9} {4C3F6E69-0FB4-41D5-8D8F-2E48B033A3EF} = {CE4ABC8D-3F54-49AA-BA5A-DD47E7CEB56B} {08096F4C-2BB3-4860-B0CA-9EC6A09EC377} = {D3C704D0-FB95-42BA-BBF1-E7360491551F} + {42DD8662-FBD2-47B8-8740-17807E17EF5A} = {E08722A6-C1B6-4C83-983C-809BF721D6F1} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {61F7FB11-1E47-470C-91E2-47F8143E1572} diff --git a/NuGet.config b/NuGet.config index 611c5b49..57ffdbb8 100644 --- a/NuGet.config +++ b/NuGet.config @@ -4,7 +4,7 @@ - +