Resolved Sliding UIpickerView?

Discussion in 'iPhone/iPad Programming' started by mistergreen2011, Apr 5, 2011.

  1. mistergreen2011, Apr 5, 2011
    Last edited: Apr 9, 2011

    macrumors member

    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?

  2. macrumors 68030


    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.
  3. macrumors member

    ok, thanks.
    I thought I was missing a UI somewhere. So I'll have to create this by view.
  4. mistergreen2011, Apr 7, 2011
    Last edited: Apr 7, 2011

    macrumors member

    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?

  5. macrumors 68030


    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.
  6. macrumors member

    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.
  7. macrumors 68030


    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.
  8. macrumors member

    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.
  9. macrumors member

    help with code

    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];

  10. Moderator


    Staff Member

    If you use a modal view, and configure it properly, it will slide in for you.
  11. macrumors 68030


    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.
  12. macrumors member

    I don't want the sliding content to take over the screen so I won't be using the modal view.
  13. Moderator


    Staff Member

    Alright. Just wanted to be certain you weren't making things harder for yourself than necessary.
  14. macrumors 68030


    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|UIViewAutoresizingFlexibleTopMargin|UIViewAutoresizingFlexibleBottomMargin;
    		[progress startAnimating];
    		backgroundView.alpha = 0.6f;
    		backgroundView.backgroundColor = [UIColor blueColor];
    		backgroundView.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin|UIViewAutoresizingFlexibleRightMargin|UIViewAutoresizingFlexibleTopMargin|UIViewAutoresizingFlexibleBottomMargin|UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight;
    		[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];
  15. macrumors member

    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.

Share This Page