PDA

View Full Version : [Resolved] Sliding UIpickerView?




mistergreen2011
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?

thanks.



PhoneyDeveloper
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.

mistergreen2011
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.

mistergreen2011
Apr 7, 2011, 07:15 PM
HI,
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?

Thanks.

PhoneyDeveloper
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.

mistergreen2011
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.

PhoneyDeveloper
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.

mistergreen2011
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.

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


Slider.h
@interface Slider : UIViewController {

}

@property (retain) IBOutlet UIView *sliderPane;

@end
-------------------------------------------------------------
Slider.m
- (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];

}

-------------------------------------------------------------
FirstScreen.h
@interface FirstScreen : UIViewController {

}

- (IBAction) slideButton:(id) sender;

@end

-------------------------------------------------------------
FirstScreen.m
- (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];
NSLog(@"pressed");

}





thanks

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

PhoneyDeveloper
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.

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

dejo
Apr 8, 2011, 12:14 PM
thanks,
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.

PhoneyDeveloper
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;
}
else
{
// 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];
}

mistergreen2011
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.