Alex Sorokoletov Notes     About     Archive     Feed

MaterialDateTimePicker bindings for Xamarin.Android apps

Bindings for MaterialDateTimePicker for Xamarin.Android apps

One of the good libraries for Android apps made in Material design is the “Material DateTime Picker” from @wdullaer. Here is a short article how to create Xamarin.Android bindings library to consume that awesome picker in your Xamarin.Android applications.

TLDR: https://github.com/alexsorokoletov/Xamarin.Wdullaer.MaterialDateTimePicker

Creating java library bindings for Xamarin.Android

There is an official guide from Xamarin: Binding a Java Library - Consuming Java libraries from C#

First, we need to get the JAR/AAR file. Looking at github page, we can see Maven banner. It means that we can grab a binary from Maven so let’s go there and do it:

https://repo1.maven.org/maven2/com/wdullaer/materialdatetimepicker/2.2.0/

Next, following the Xamarin guide, we will see 3 errors:

Vendor/MaterialDateTimePickerBinding/obj/Debug/generated/src/Com.Wdullaer.Materialdatetimepicker.Date.MonthView.cs(34,34): 
  Error CS0533: `Com.Wdullaer.Materialdatetimepicker.Date.MonthView.MonthViewTouchHelper.GetVisibleVirtualViews(System.Collections.Generic.IList<Java.Lang.Integer>)' 
  hides inherited abstract member `Android.Support.V4.Widget.ExploreByTouchHelper.GetVisibleVirtualViews(System.Collections.Generic.IList<Java.Lang.Integer>)'
  (CS0533) (MaterialDateTimePickerBinding)
 Vendor/MaterialDateTimePickerBinding/obj/Debug/generated/src/Com.Wdullaer.Materialdatetimepicker.Date.MonthView.cs(36,36): Error CS0534: `Com.Wdullaer.Materialdatetimepicker.Date.MonthView.MonthViewTouchHelper' does not implement inherited abstract member `Android.Support.V4.Widget.ExploreByTouchHelper.GetVisibleVirtualViews(System.Collections.Generic.IList<Java.Lang.Integer>)' (CS0534) (MaterialDateTimePickerBinding)

and

 Vendor/MaterialDateTimePickerBinding/obj/Debug/generated/src/Com.Wdullaer.Materialdatetimepicker.Time.Timepoint.cs(23,23): Error CS0535: `Com.Wdullaer.Materialdatetimepicker.Time.Timepoint' does not implement interface member `Java.Lang.IComparable.CompareTo(Java.Lang.Object)' (CS0535) (MaterialDateTimePickerBinding)

1st and 2nd are pretty simple. As these methods most definitely will not be consumed from C# side, we can just remove these methods from bindings.

For that we use <remove-node /> instruction in Metadata.xml.

<remove-node path="/api/package[@name='com.wdullaer.materialdatetimepicker.date']/class[@name='MonthView.MonthViewTouchHelper']/method[@name='getVisibleVirtualViews' and count(parameter)=1 and parameter[1][@type='java.util.List&lt;java.lang.Integer&gt;']]" />
<remove-node path="/api/package[@name='com.wdullaer.materialdatetimepicker.date']/class[@name='MonthView.MonthViewTouchHelper']" />

To solve 3rd problem we need to add a partial class to Additions folder:

    
namespace Com.Wdullaer.Materialdatetimepicker.Time
{
    /*
     * add partial class due to Java generics and IComparable interface in Xamarin.Android
     * Vendor/MaterialDateTimePickerBinding/obj/Debug/generated/src/Com.Wdullaer.Materialdatetimepicker.Time.Timepoint.cs(23,23): Error CS0535: 'Com.Wdullaer.Materialdatetimepicker.Time.Timepoint' does not implement interface member 'Java.Lang.IComparable.CompareTo(Java.Lang.Object)' (CS0535) (MaterialDateTimePickerBinding)
     * https://forums.xamarin.com/discussion/1950/binding-jar-file-with-class-that-implements-java-lang-icomparable
     */
    public partial class Timepoint
    {
        int Java.Lang.IComparable.CompareTo(Java.Lang.Object obj)
        {
            return CompareTo ((Timepoint) obj);
        }
    }
}

Solution to this issue I found on Xamarin Forums.

As usual, very helpful were comments and examples from brendanzagaeski with different approaches to different java-to-csharp binding problems. Links to these examples are in the end of the page.

JAR/AAR dependencies

This library we are binding now has only one dependency: https://github.com/wdullaer/MaterialDateTimePicker/blob/master/library/build.gradle#L23

It is a com.android.support:support-v4:23.1.1 which translates to Xamarin Nuget package called Xamarin.Android.Support.v4 of version 23.1.1.

So we will just add this Nuget package to our bindings project and that’s it. Clean and Build the project and you should see 0 errors. Yaay!

How to use this library (examples)

On C# side what you need to do is following:

  1. reference the bindings project in your app project
  2. in your activity implement interface OnTimeSetListener/OnDateSetListener
  3. create a datepicker and show it

These steps are described in the Readme.md file of the original library

//implement OnDateSetListener
public class HomeView : BaseActionBarView<HomeViewModel>,  
Com.Wdullaer.Materialdatetimepicker.Date.DatePickerDialog.IOnDateSetListener
        
private void OnChooseDateButtonClick(object sender, EventArgs e)
{
    Java.Util.Calendar now = Java.Util.Calendar.Instance;
    Com.Wdullaer.Materialdatetimepicker.Date.DatePickerDialog dpd = 
        Com.Wdullaer.Materialdatetimepicker.Date.DatePickerDialog.NewInstance(
        this,
        now.Get(Java.Util.CalendarField.Year),
        now.Get(Java.Util.CalendarField.Month),
        now.Get(Java.Util.CalendarField.DayOfMonth)
    );
    dpd.Show(FragmentManager, "Datepickerdialog");
}

public void OnDateSet(Com.Wdullaer.Materialdatetimepicker.Date.DatePickerDialog p0, int p1, int p2, int p3)
{
    p0.Dismiss();
}
		

Make sure you are using the same version of Xamarin.Android.Support.v4 package in your application project.

Demo

Material Date Time Picker in Xamarin.Android app

Source code

See Xamarin.Wdullaer.MaterialDateTimePicker github repository. Clone it and use it or just add as a submodule.

Improving further

One thing definitely open for improvement is parameter names. Right now in many places it’s just p0, p1, p2, p3.

Naming them hour, minute, second, isAmPm would make code cleaner and easier to understand.

So if you feel like fixing something feel free to submit pull request. (Or if you know how to fix these names automaticall - let me know, please).


If you liked this post, you can share it with your followers or follow me on Twitter!