Lexa

WPF, C#, Objective C and a little Math

UIDatePicker / UIPickerView gradients and the structure

I wanted to implement my own iOS control which should look similar to UIPickers. And of course, I was really interested in the way how these controls are implemented. At least, which windows are composed together to create such a brilliant experience. It was also interesting to learn how gradients are used there. Meanwhile I found this article: http://aralbalkan.com/2985, but the actions described there I found too complicated.

Then I got the idea that I can just simply go through picker subviews and try to hide/show them programmatically. And this worked – now I can see how picker is composed! Moreover, I can render selected view in an image and send it using e-mail for gradient analysis:

 

To create this App, I started with simple UIView based application, and put all needed controls on top of the main view: UIDatePicker, UIImageView, UISlider and UIButton.

Then I added outlets for all controls in the header:

@property (retain, nonatomic) IBOutlet UIDatePicker *picker;
@property (retain, nonatomic) IBOutlet UISlider *slider;
@property (retain, nonatomic) IBOutlet UIImageView *imageView;

- (IBAction) sliderChanged:(id) sender;

When view (and the picker) are completely loaded, its time to initialize slider:

- (UIView*)pickerSubs {
    return [picker.subviews objectAtIndex:0];
}

- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];

    slider.minimumValue = 0;
    slider.maximumValue = [self pickerSubs].subviews.count;
    slider.value = 0;

    previousSelection = 0;
}

When slider value is changed, the next selected window disappears:

-(IBAction) sliderChanged:(id) sender {
    if (previousSelection > 0) {
        // Show subview.
        ((UIView *)[[self pickerSubs].subviews
                    objectAtIndex:previousSelection - 1]).hidden = NO;

        imageView.image = nil;
    }

    previousSelection = (int)slider.value;

    if (previousSelection > 0)
    {
        // Render subview.
        UIView *subview = (UIView *)[[self pickerSubs].subviews
                                     objectAtIndex:previousSelection - 1];

        UIGraphicsBeginImageContext(subview.bounds.size);
        [subview.layer renderInContext:UIGraphicsGetCurrentContext()];
        UIImage *resultingImage = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        imageView.image = resultingImage;

        // Hide subview.
        subview.hidden = YES;
    }
}

Simple solution, a lot of interesting info as a result. Nice work, Apple!

 


Categorised as: iOS, UI


Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>