View Full Version : [Resolved] Sliding UIpickerView?

Apr 5, 2011, 11:34 PM
When you click a <select> input on a web page, a pickerView slides up from the bottom and lets you pick an item. it also has a 'done' button in case you want to exit the view.

How is this done with a UIpickerView or is it something else?


Apr 6, 2011, 12:21 AM
The basic idea is simple.

Create a view. Add to it whatever subviews you need, pickerview, done button etc. When you create the view have its frame be offscreen to the bottom. AddSubview the view to something that's onscreen and then use UIView animation to animate the frame of the view onscreen. Animate the view offscreen in response to the done button.

Apr 6, 2011, 05:26 PM
ok, thanks.
I thought I was missing a UI somewhere. So I'll have to create this by view.

Apr 7, 2011, 07:15 PM
Any idea how I can make is animation view more modular?

I have several UIViewControllers and they have buttons that will call a sliding pickerView. The dataSource on the pickerView would be different but everything else is the same.

Right now I have an animated view in one ViewController but I'm guessing the other ViewController will have problems calling this and it appears when other ViewControllers are active?


Apr 7, 2011, 09:34 PM
I guess you're asking how to encapsulate the animation behavior so it can be easily reused. Good question.

I haven't implemented this so I can only give you some ideas off the top of my head.

One way would be to write an animatingView class. This view has a couple methods that animate the view onscreen and offscreen. Create one of these views. Add any subviews that you like. The animating view has to be added to the view hierarchy (addSubview) with a frame that is offscreen and then animated onscreen and later animated offscreen. The view also has to be removed from the view hierarchy (removeFromSuperview) once its animation offscreen has completed.

Another way is to add the functionality, which is several methods, to a UIViewController subclass and then derive all of your other view controllers from this subclass.

It's also possible that you could add the functionality to UIViewController with a category. It seems that there's probably no state that needs to be maintained so you don't need to add any ivars. Just a few methods. Adding this as a category might be a good way to do this.

Without implementing it myself I'm not sure which of these strategies will work and which is the best.

Apr 7, 2011, 10:20 PM
Thanks, yes I mean encapsulation.

I'll investigate these strategies. I can take the easy way out and recreate a new animated view with every viewController but it just seems wrong.

Apr 7, 2011, 10:28 PM
Well, you're going to create a new view each time, nothing wrong with that. You'd just prefer not to have to duplicate the code. Think of it like the navigation controller with pushViewController and popViewController. You want to implement something like those methods, except you're pushing a view and popping a view, and doing the related animations.

Apr 7, 2011, 11:57 PM
Well, I'm still learning this so I might wind up taking the easy way and copy the code.
From what I can see, Categories might not work out since it's restrictive.

Apr 8, 2011, 09:15 AM
I'm subclassing UIViewController but it's not working. The animated view does not show up.

@interface Slider : UIViewController {


@property (retain) IBOutlet UIView *sliderPane;

- (void)viewDidLoad

[super viewDidLoad];
// Do any additional setup after loading the view from its nib.

CGRect sliderFrame = sliderPane.frame;
sliderFrame.origin.y = 300;
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.5];
[UIView setAnimationDelay:1.0];
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];

sliderPane.frame = sliderFrame;

[UIView commitAnimations];


@interface FirstScreen : UIViewController {


- (IBAction) slideButton:(id) sender;


- (void)slideButton:(id)sender {
//the problem is here?
Slider *pickerview = [[Slider alloc] init];
CGRect sliderFrame = CGRectMake(0.0f, 0.0f, 320.0f, 416.0f);
self.view = [[[UIView alloc] initWithFrame:sliderFrame] autorelease];
[self.view addSubview:pickerview.view];

[pickerview release];



Apr 8, 2011, 09:21 AM
If you use a modal view, and configure it properly, it will slide in for you.

Apr 8, 2011, 10:07 AM
Maybe I misunderstood the question. Of course a modal view will slide in from the bottom and slide off. But a modal view will cover the entire screen. If you want a transparent background or you want a view that only partly covers the screen you need to do it like I described. If you just want a view to slide on and cover the screen then use a modal view.

@misterGreen, in order to do this like I describe you don't present the sliding view from viewDidLoad. You present it in response to another message that the view controller provides and calls whenever it needs to present the picker. I think your Slider class is meant to be a UIView subclass.

Apr 8, 2011, 11:16 AM
I don't want the sliding content to take over the screen so I won't be using the modal view.

Apr 8, 2011, 12:14 PM
I don't want the sliding content to take over the screen so I won't be using the modal view.
Alright. Just wanted to be certain you weren't making things harder for yourself than necessary.

Apr 8, 2011, 01:34 PM
Here's some code I have that does this. These methods are in a view controller and the point is to show a full screen view that's transparent, blue, and has a spinning progress view in the center.

// ==============================================================
// hideShowProgressView
// ==============================================================

- (void)hideShowProgressView:(BOOL)inShow
CGRect newFrame;
CGRect windowframe = [[UIScreen mainScreen] bounds];

// The main screen frame is always the same so we need to go offscreen
// to a different place depending on the interface orientation
// If landscape the sizes will be backwards, origin is always 0, 0
if (UIInterfaceOrientationIsLandscape(self.interfaceOrientation))
CGFloat width = windowframe.size.width;
windowframe.size.width = windowframe.size.height;
windowframe.size.height = width;

CGRect offframe = windowframe;

offframe.origin.y += offframe.size.height + 10;

if (inShow)
// Build and show the progress view
UIView* backgroundView = [[UIView alloc] initWithFrame:offframe];
UIActivityIndicatorView* progress = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];

// Center the activity indicator view in the backgroundView
CGRect progressFrame = progress.frame;
progress.frame = CGRectMake(offframe.size.width/2 - progressFrame.size.width/2, offframe.size.height/2 - progressFrame.size.height/2, progressFrame.size.width, progressFrame.size.height);
progress.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin|UIViewAutoresizingFlexibleRightMargin|UIViewAutoresizingFlexibl eTopMargin|UIViewAutoresizingFlexibleBottomMargin;
[progress startAnimating];

backgroundView.alpha = 0.6f;
backgroundView.backgroundColor = [UIColor blueColor];
backgroundView.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin|UIViewAutoresizingFlexibleRightMargin|UIViewAutoresizingFlexibl eTopMargin|UIViewAutoresizingFlexibleBottomMargin|UIViewAutoresizingFlexibleWidth|UIViewAutoresizing FlexibleHeight;

[backgroundView addSubview:progress];
self.progressView = backgroundView;
[progress release];
[backgroundView release];

// Add the progress view to the navigation controller view and it covers everything
// and also rotates correctly
[self.navigationController.view addSubview:backgroundView];

newFrame = windowframe;
// Hide the progress view
newFrame = offframe;

// Animate the view on or off the screen
// need to remove the view when the animation finishes
[UIView beginAnimations:@"animation1" context:NULL];
[UIView setAnimationDuration:0.3];
if (! inShow)
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:@selector(animationDidStop:finished:context:)];

self.progressView.frame = newFrame;

[UIView commitAnimations];

// ==============================================================
// animationDidStop:finished:context:
// ==============================================================

-(void)animationDidStop:(NSString*)animationID finished:(NSNumber*)finished context:(void *)context
[self.progressView removeFromSuperview];
self.progressView = nil;

- (void)showProgressView
if (! self.progressView)
[self hideShowProgressView:YES];

- (void)hideProgressView
[self hideShowProgressView:NO];

Apr 9, 2011, 09:33 AM
Thanks a lot guys.
I got it working.

The hardest part was subclassing UIView and instantiating it when I need it.

I'm getting the hang of iOS and O-C. Not too bad at all after a month of studying.