http://www.timespace.org/2008/07/11/the-abusive-pickerview/
iPhone SDK 2.0 is a welcome thing but some of the controls make you
wonder how they are supposed to be easy to work with. One thing iPhone
devs will need that has driven me nuts because so few implement it right
yet in any of the apps I’ve seen it in. The odometer style pickerview,
no one seems to understand so I’m going to break down the UIPickerView
into its most basic components hopefully this helps someone with the
spare time to develop for the iphone to create some kewl apps that use
it to make the ui experience better.
First here is some sample code that should help you better understand
how to virtually wrap the pickerview. What we have in the titleForRow
method is an array the returns the value of the selected row modulus 10.
This ensures we stay in our array and return the appropriate string
label for the row we want. This means no matter what “row” the ui
thinks we are in we will be returning what we want them to see for that
row giving us the virtual wrap we want. The return could just as easily
be simply the row%10 as an NSString without the array for a basic
odometer style picker.
Some other code that helps us with the illusion is the
numberOfRowsInComponent method. In here we return the number of
possible rows to select. I started off using NSMaxIneger and quickly
found this breaks everything so I bumped the number down until I got
around 16384. This allows you to wrap around and around and force the
user into having to be pretty dedicated to reach the end of the list
breaking the illusion. Change the number down to 32 to see the end of
the list and get a better feel for what is going on in the background as
the delegate methods aid in rendering the UI.
Now what you really want to happen is if they hit the end of the list
repopulate it and the easiest way to do this is redirect the list to
its own middle. But if every time you did this you took them to the
middle it would mess up their current selection so the algorithm has to
be a little smarter and offset them to their current selection. There
are three pieces to this. The first is the didSelectRow this delegate
is called when the user stops moving the control. From here we want to
call a delegate that is called when the control loads as well
pickerViewLoaded. When the pickerViewLoaded delegate is called we setup
the same max as the max returned in numberOfRowsInComponent because we
want to go to the middle of the possible selections. We then take the
max divided by two for the middle then use that value mod 10 to get the
offset to take us to the nearest row divisible by ten. From here we can
take the current selected row modulus ten and use that as the offset
tot he current row we want them to be on. When we select this row
without animation there should be no apparent movement to the end user
and they should now be back towards the middle of the list.
The final piece of code here should enable us to return the number of
horizontal components in the pickerview. As you can see the other
methods have a component method that returns which column of data you
are looking at. There is additional programming required for dealing
with this but it shouldn’t be to difficult to figure out once you
understand what you’re dealing with in the basics of the pickerview.
If your anything like me while the interface is unique but the
loading mechanism I think could be significantly optimized but I think
the user experience is one that as a developer I can live with because
even with the overhead on the device it seems to work well enough. I
would also like to disclaim this isn’t meant to be a definitive on the
subject of the PickerView only a guide so application developers wanting
to work with this control can do so without going bald because of the
complexities of the control.
No comments:
Post a Comment