Date Picker Wheel Widget

Vote up!

A Date Picker Wheel widget that actually adjusts for the different number of days in each months, and even accounts for leap years!

The Problem

The traditional PickerWidget from the widget library (widget.newPickerWheel()) is limited, since you can't really modify the contents of the columns once you create it. This presents a problem for picking a date, because months all have a different number of days. The PickerWidget example code walks you through how to use it for a date, but if you follow that example, your end users could end up picking a date that doesn't exist like February 31.

The Solution

Now, I'm sure somebody can improve upon what I've started here, but this has worked great for me so far! Using a timer, the widget checks for when the selected month (and year, to account for leap years) has changed. If the number of days in the middle day column needs to be updated, the PickerWidget it uses under the hood is swapped out for a new one, with your date selection maintained.

Adding To Your App

First, download the datePickerWheel.lua file to your project directory. Then, include the necessary modules in your scene:

local widget = require("widget")

-- Create a forward reference for the widget.
local datePicker

Next, create the widget. If you're using composer, this would likely go in your scene:create function:

-- Create the widget. Depending on where you reference the wd
datePicker = widget.newDatePickerWheel(currYear, currMonth, currDay)

-- Position it however you like.
-- The datePicker is a group containing a picker wheel, so you must use anchorChildren to move everything all seamlessly.
datePicker.anchorChildren = true
datePicker.anchorX = 0.5
datePicker.anchorY = 0
datePicker.x = display.contentCenterX
datePicker.y = 0

Clean it up like any other widget when ready:

datePicker = nil

Finally, access the user's selection just like you would with a normal PickerWidget:

local values = datePicker:getValues()

-- CORONA BUG: Sometimes the values can be nil.
-- This happens when one of the tables stopped scrolling but hasn't "snapped" to a selected index.
-- Prompt the user to fix the bad column.
if not values[1] then
    native.showAlert(_M.appName, "Please make sure a month is selected.", {"OK"})
elseif not values[2] then
    native.showAlert(_M.appName, "Please make sure a day is selected.", {"OK"})
elseif not values[3] then
    native.showAlert(_M.appName, "Please make sure a year is selected.", {"OK"})
    displayText.text = values[1].value .. " " .. values[2].value .. ", " .. values[3].value

Be sure to try out the example.lua scene for a working example. Let me know what you think, and if you have any improvements!

Works with Corona build #: