Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UIPickerView infinite rows

As seen in UIDatePicker you can scroll up endlessly (as well as down for that matter). I want to accomplish that too, because I want people to select a date such as:

1 January, 2010 2 January, 2010 ... 30 December, 2010 31 December, 2010 1 January, 2011 ..

So it can go on forever. How would I accomplish this? Since I can only give a specific amount of rows in the delegate.

like image 801
Mark Avatar asked Sep 01 '10 13:09

Mark


4 Answers

I don't think you can actually make the UIPickerView loop, but the way I've done it in the past is to return a really large number from numberOfRowsInComponent and then calculate the modulus of the row to return the appropriate view from viewForRow, like this:

// picker data source:
-(NSInteger) pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger) component
{
    // to make it look like the picker is looping indefinetly,
    // we give it a really large length, and then in the picker delegate we consider
    // the row % (actual length) instead of just the row.
    return INT16_MAX;
}


// picker delegate:
-(UIView *) pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger) row forComponent:(NSInteger) component reusingView:(UIView *)view
{
    // to make it look like the picker is looping indefinetly,
    // we give it a really large length in the picker data source, and then we consider
    // the row % actual_length instead of just the row.
    row = row % actual_length;
    // where actual length is the number of options that will be looping

    // ... do whatever
}

and in your initialization:

- (void)viewDidLoad {
    [super viewDidLoad];

    // ... whatever other initialization... 

    // to make it look like the picker is looping indefinetly ,
    // we give it a really large length in the picker data source, and then we consider
    // the row % actual_length instead of just the row, 
    // and we start with the selection right in the middle, rounded to the
    // first multiple of actual_length so we start the selection on 
    // the first option in the list.
    [myPicker selectRow:(INT16_MAX/(2*actual_length))*actual_length inComponent:0 animated:NO];
}
like image 75
filipe Avatar answered Oct 24 '22 08:10

filipe


I agree with most of the above (filipe) answer, just one thing: yes you can make the UIPickerView loop:

- (void)viewDidLoad 
{
    [super viewDidLoad];
    [myPicker selectRow:(INT16_MAX/(2*actual_length))*actual_length inComponent:0 animated:NO];
}

-(NSInteger) pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger) component
{
    return INT16_MAX; // Just some big number
}

-(UIView *) pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger) row forComponent:(NSInteger) component reusingView:(UIView *)view
{
row = row % actual_length; // This is the value you should use as index of your data

// And here comes the trick, move the wheel back again to the middle rows
// so the user can virtually loop in any direction
pickerView selectRow:(row + (INT16_MAX/(2*actual_length))*actual_length)  inComponent:component animated:NO];
}

All the above answers and this one are practically the same.This is what livingtech is explaining but with code. And filipe's answer is also right, but if you want an stricter answer just return to the appropiate middle row when the user stops scrolling. Anyway, doing so doesn't offer any practical advantage because the user will get tired sooner than scrolling INT16_MAX/2 times.

like image 32
FranMowinckel Avatar answered Oct 24 '22 08:10

FranMowinckel


High level: Specify some finite number of rows in your delegate. Then detect as you get toward the top or bottom of those rows and change the delegate so the row is actually in the middle (or top, or whatever). You would obviously need to change the table's location by using one of the scrolling methods (presumably without animation so it happens without the user knowing).

Make sense? I've never done this, but it should be theoretically possible.

like image 42
livingtech Avatar answered Oct 24 '22 10:10

livingtech


Try this component: http://dev.doukasd.com/2011/04/infinite-scrolling-dial-control-for-ios/

It should be as simple as instantiating 2 DialControllers and setting the values you need. The example included is quite similar.

like image 1
Dimitris Avatar answered Oct 24 '22 09:10

Dimitris