A Replacement For ActionSheet Date Picker
In the earlier days of Xamarin.iOS development (up to iOS 7), one of the more useful recipes from the Xamarin Documentation was the ActionSheet Date Picker. Adding a DatePicker as a subview of a
UIActionSheet was a very convenient way to display a DatePicker to the user. The Action Sheet would behave as it usually would, and you could modify it to slide from the bottom and only take up the bottom portion of the screen. After the user selects the date and taps on “Done”, the ActionSheet would then slide back down. Because of the behavior of the ActionSheet, this was a great way to provide a Modal Date Picker. However, this recipe no longer works on iOS 8 due to “misuse” of the
UIActionSheet. I created an alternative, with full source code and sample app that replaces the ActionSheet Date Picker that is free to use.
An Ominous Hidden Warning
If you even ran the ActionSheet Date Picker, you may have noticed a few warnings/errors that appeared in your output window when the ActionSheet Date Picker would launch on an iOS 7 device or Simulator. The warning looked something like this:
<Error>: CGContextSetFillColorWithColor: invalid context 0x0. This is a serious error. This application, or a library it uses, is using an invalid context and is thereby contributing to an overall degradation of system stability and reliability. This notice is a courtesy: please fix this problem. It will become a fatal error in an upcoming update.
Though this was only a warning, the app remained stable and executed as one would expect. I myself remember seeing these errors and wondered why was I getting these messages. What scared me the most was the last two sentences of the message. I decided to do a little investigation and as it turns out, Apple never intended the
UIActionSheet to be used in this way. From the Apple Documentation, there is a little note that states:
UIActionSheet is not designed to be subclassed, nor should you add views to its hierarchy. If you need to present a sheet with more customization than provided by the UIActionSheet API, you can create your own and present it modally with presentViewController:animated:completion:.
So as it turns out, Apple does not want you subclassing or adding your own subviews (like an
UIDatePicker) to the ActionSheet. And starting with iOS 7, it gave warnings in your output window to fix the problem, or else. So now, the “upcoming update” is here. Welcome to iOS 8. And as promised, subclassing the
UIActionSheet or adding your own views to it now produces a fatal error that crashes your app.
A Possible Solution
In the Apple Documentation (shown above), the last sentence stated that you can create your own (in the form of a UIViewController) and present it modally using the
PresentViewController() method. Several months ago I was in a dilemma. I knew that iOS 8 was going to be released sometime during the Fall of 2014. That’s a given for sure, but at the time I didn’t know the exact date. I could either fix this issue now, or wait down the line and, most likely, be in a panic to fix this critical issue at the last minute. Fortunately, I decided to fix the problem then because I didn’t want to put myself into a position to rush an emergency fix for iOS 8.
So I went ahead and created the
ModalPickerViewController. This took me about a day to flush out. I thought it was going to be straight forward and easy to code up. For the most part it was, but creating the slide-up/slide-down transitions and supporting Portrait and Landscape modes proved to be a little challenging. But when it was all said and done, the output was a modal Date Picker that mimicked the ActionSheet Date Picker.
How To Use The ModalPickerViewController
ModalPickerViewController is pretty straight forward. Below is a step by step process.
Step 1: Create An Instance Of ModalPickerViewController
First, you want to create an instance of
ModalPickerViewController. The constructor accepts 3 parameters: a
ModalPickerType, a title for the header, and a reference to its parent view controller.
var modalPicker = new ModalPickerViewController(ModalPickerType.Date, "Select A Date", this)
HeaderBackgroundColor = UIColor.Red,
HeaderTextColor = UIColor.White,
TransitioningDelegate = new ModalPickerTransitionDelegate(),
ModalPresentationStyle = UIModalPresentationStyle.Custom
There are also several properties you want to initialize. The
HeaderBackgroundColor is the color of the view controller header. The
HeaderTextColor is the font color for the header text. The next two properties are really important. Set the
TransitioningDelegate to a new instance of
ModalPickerTransitionDelegate. This is what defines the slide-up/slide-down transition. Also set the
Custom. This tells the View Controller that when it is presented, it will use the
ModalPickerTransitionDelegate for its transition.
Step 2: Set Your Date Picker Mode
Next, you want to set the
DatePicker mode. You can set it to anything you want, but for this example, I’ll set it to
modalPicker.DatePicker.Mode = UIDatePickerMode.Date;
Step 3: Wire Up The OnModalPickerDismissed Event Handler
This event will fire after the user selects the date and taps on “Done”. In this event handler, you can extract the currently selected date and use it as you see fit. In this example, I’m just taking the selected date and displaying it on a UILabel called “PickedLabel”.
modalPicker.OnModalPickerDismissed += (s, ea) =>
var dateFormatter = new NSDateFormatter()
DateFormat = "MMMM dd, yyyy"
PickedLabel.Text = dateFormatter.ToString(modalPicker.DatePicker.Date);
Step 4: Show the ModalPickerViewController
The final step is to show the
ModalPickerViewController by call
await PresentViewController(modalPicker, true);
The final output should look like this:
Where To Get The Code
You can download the source code along with a Sample App by visiting my GitHub Repo at: https://github.com/SharpMobileCode/ModalPickerViewController. You’re free to use it and modify it if you need to. I only ask that if you add something useful or fix a bug, that you submit a pull request and submit your changes. I would benefit us and the rest of the community. The sample code also includes an example of using a custom Picker View. So you can use a custom picker if you want to show custom formatted dates, or anything else for that matter (a list of colors, people, states, cities, etc). It’s all in the sample.
Areas For Improvement
The ModalPickerViewController also supports landscape orientation. Though I’m not quite happy with the transition. When you rotate the device to landscape and then back to portrait, you’ll notice that the transition is a little choppy. I would rather have it be a little smoother. The
ModalPickerTransitionDelegate class is what defines the transitions. I really didn’t want to spend too much time perfecting this, but if you would like to give it a shot, feel free. 🙂
I hope you found this useful. And as usual, feel free to send me an e-mail or leave a comment. Also if you’d like to contribute and help improve this project feel free to submit a pull request on GitHub.