Reputation: 81
I have a view controller (vc) with a UIPickerView on it which needs to slide up from the bottom half of the screen.
Using:
ViewControlelr *vc = [self.storyboard instantiateViewControllerWithIdentifier: @"VC"];
[self presentViewController:vc animated:YES completion:nil]
makes the page display in fullscreeen
Ive read that putting UIPickerViews in activity sheets is not a good idea anymore, any suggestions?
Upvotes: 1
Views: 928
Reputation: 1673
Ive read that putting UIPickerViews in activity sheets is not a good idea anymore, any suggestions?
In all honesty, it was never a good idea but it became kind of an underground standard. If you are displaying it after the user sets the text field as the firstResponder, you can set the UIPickerView as the UITextField's inputView. If you want a tool bar on top of it, create one and set it as the UITextField's inputAccessoryView.
If this is not the case, I would suggest creating a UIView container to hold the UIPickerView and set its y to the height of the screen. When you want to show it, use UIView animations to change the y to the height of screen minus the height of the container.
Alternatively you could just do the same thing without a UIView container but you may lose some control over how you want to present the UIPickerView since its size is fixed.
EDIT 1:
I created a container that holds a UIPickerView though it seems to only be presented correctly presentable in portrait mode. Feel free to expand upon it to make it orientation friendly.
//
// AbstractPickerPresenter.h
// ShowDatePickerView
//
// Created by Christopher John Morris on 10/10/13.
// Copyright (c) 2013 Christopher John Morris. All rights reserved.
//
#import <UIKit/UIKit.h>
@protocol PickerPresenterDelegate;
@protocol PickerPresenterButtonDelegate;
@interface PickerPresenter : UIView {
UIView *pickerContainer;
id<PickerPresenterButtonDelegate>buttonDelegate;
}
/*
* Helper constant used for measuring frames
*/
@property (nonatomic, readonly) CGFloat pickerHeight;
/*
* Helper constant used for measuring frames
*/
@property (nonatomic, readonly) CGFloat navBarHeight;
/*
* Automatically hides view when Cancel is clicked.
* Default is YES
*/
@property (nonatomic) BOOL hideOnDoneClicked;
/*
* Automatically hides view when Done is clicked.
* Default is YES
*/
@property (nonatomic) BOOL hideOnCancelClicked;
/*
* Raises the view into visible position
*/
- (void) show;
/*
* Removes the view out of visible position
*/
- (void) hide;
/*
* Sets titles for buttons. Size of buttons adujst based on textsize
*/
- (void)setCancelButtonTitle:(NSString *)title;
- (void)setDoneButtonTitle:(NSString *)title;
@end
/*
* Delegate that is used strictly by subclasses to react
* to button presses.
*/
@protocol PickerPresenterButtonDelegate
@required
- (void) didCancel;
- (void) didSave;
@end
...
//
// AbstractPickerPresenter.m
// ShowDatePickerView
//
// Created by Christopher John Morris on 10/10/13.
// Copyright (c) 2013 Christopher John Morris. All rights reserved.
//
#import "PickerPresenter.h"
@interface PickerPresenter()
/*
* Tint color of buttons
*/
@property (nonatomic, strong) UIColor *tintColor;
/*
* Cancel button
*/
@property (nonatomic, strong) UIButton *cancelButton;
/*
* Done button
*/
@property (nonatomic, strong) UIButton *doneButton;
/*
* Black facade that appears behind the picker container
* and is the size of the current UIWindow
*/
@property (nonatomic, strong) UIView *facadeView;
/*
* Helper constant used to make animations consistent
*/
@property (nonatomic, readonly) NSTimeInterval animationInterval;
@end
@implementation PickerPresenter
- (id)init {
self = [super init];
if (self) {
[self initializeView];
[self initializeViewContainer];
[self initializeCancelButton];
[self initializeDoneButton];
}
return self;
}
- (void) initializeView {
[self setHidden:YES];
CGFloat height = [[UIScreen mainScreen] bounds].size.height;
self.frame = CGRectMake(0, height, [[UIScreen mainScreen] bounds].size.width, height);
self.backgroundColor = [UIColor clearColor];
self.tintColor = [[[[UIApplication sharedApplication] delegate] window] tintColor];
self.facadeView = [[UIView alloc] initWithFrame:self.frame];
self.facadeView.backgroundColor = [UIColor blackColor];
self.facadeView.alpha = 0.4;
[self addSubview:self.facadeView];
self.hideOnDoneClicked = YES;
self.hideOnCancelClicked = YES;
}
- (void) initializeViewContainer {
CGFloat containerHeight = (self.pickerHeight + self.navBarHeight);
pickerContainer = [[UIView alloc] initWithFrame:CGRectMake(0,
self.frame.size.height + containerHeight,
self.frame.size.width,
containerHeight)];
pickerContainer.backgroundColor = [UIColor whiteColor];
[self addSubview:pickerContainer];
}
- (void) initializeCancelButton {
self.cancelButton = [[UIButton alloc] init];
[self.cancelButton setTitleColor:self.tintColor forState:UIControlStateNormal];
[self.cancelButton setTitleColor:[UIColor blueColor] forState:UIControlStateHighlighted];
[self.cancelButton setTitle:@"Cancel" forState:UIControlStateNormal];
self.cancelButton.titleLabel.font = [UIFont fontWithName:@"HelveticaNeue" size:20];
CGSize size = [self.cancelButton.titleLabel.text sizeWithFont:self.cancelButton.titleLabel.font];
self.cancelButton.frame = CGRectMake(10, 0, size.width, self.navBarHeight);
[self.cancelButton addTarget:self action:@selector(cancel) forControlEvents:UIControlEventTouchUpInside];
[pickerContainer addSubview:self.cancelButton];
}
- (void) cancel {
[buttonDelegate didCancel];
}
- (void) done {
[buttonDelegate didSave];
}
- (void) initializeDoneButton {
self.doneButton = [[UIButton alloc] init];
[self.doneButton setTitleColor:self.tintColor forState:UIControlStateNormal];
[self.doneButton setTitleColor:[UIColor blueColor] forState:UIControlStateHighlighted];
[self.doneButton setTitle:@"Done" forState:UIControlStateNormal];
self.doneButton.titleLabel.font = [UIFont fontWithName:@"HelveticaNeue" size:20];
[self.doneButton addTarget:self action:@selector(done) forControlEvents:UIControlEventTouchUpInside];
CGSize size = [self.doneButton.titleLabel.text sizeWithFont:self.doneButton.titleLabel.font];
self.doneButton.frame = CGRectMake(self.frame.size.width - (size.width + 10), 0, size.width, self.navBarHeight);
[pickerContainer addSubview:self.doneButton];
}
- (void)setCancelButtonTitle:(NSString *)title {
[self.cancelButton setTitle:title forState:UIControlStateNormal];
CGSize size = [self.cancelButton.titleLabel.text sizeWithFont:self.cancelButton.titleLabel.font];
self.cancelButton.frame = CGRectMake(10,
0,
size.width,
self.cancelButton.frame.size.height);
}
- (void)setDoneButtonTitle:(NSString *)title {
[self.doneButton setTitle:title forState:UIControlStateNormal];
CGSize size = [self.doneButton.titleLabel.text sizeWithFont:self.doneButton.titleLabel.font];
self.doneButton.frame = CGRectMake(self.frame.size.width - (size.width + 10),
self.doneButton.frame.origin.y,
size.width,
self.doneButton.frame.size.height);
}
- (void) show {
self.alpha = 0.0;
self.frame = CGRectMake(self.frame.origin.x,
self.frame.origin.y - self.frame.size.height,
self.frame.size.width,
self.frame.size.height);
self.facadeView.frame = CGRectMake(self.frame.origin.x,
self.frame.origin.y,
self.frame.size.width,
self.frame.size.height);
[[[UIApplication sharedApplication] keyWindow] addSubview:self];
[UIView animateWithDuration:self.animationInterval animations:^{
[self setHidden:NO];
self.alpha = 1.0;
} completion:^(BOOL finished) {
[UIView animateWithDuration:self.animationInterval animations:^{
pickerContainer.frame = CGRectMake(pickerContainer.frame.origin.x,
self.frame.size.height - pickerContainer.frame.size.height,
pickerContainer.frame.size.width,
pickerContainer.frame.size.height);
} completion:nil];
}];
}
- (void) hide {
CGFloat height = [[UIScreen mainScreen] bounds].size.height;
[UIView animateWithDuration:self.animationInterval animations:^{
pickerContainer.frame = CGRectMake(0,
self.frame.size.height + pickerContainer.frame.size.height,
self.frame.size.width,
pickerContainer.frame.size.height);
} completion:^(BOOL finished) {
[UIView animateWithDuration:self.animationInterval animations:^{
self.alpha = 0.0;
} completion:^(BOOL finished) {
[self setHidden:YES];
[self removeFromSuperview];
self.frame = CGRectMake(self.frame.origin.x,
height,
self.frame.size.width,
self.frame.size.height);
self.facadeView.frame = CGRectMake(self.frame.origin.x,
self.frame.origin.y,
self.frame.size.width,
self.frame.size.height);
}];
}];
}
- (CGFloat)pickerHeight {
CGFloat const kPickerHeight = 216;
return kPickerHeight;
}
-(CGFloat)navBarHeight {
CGFloat const kNavBarHeight = 44;
return kNavBarHeight;
}
-(NSTimeInterval)animationInterval {
NSTimeInterval const kAnimationInterval = 0.2;
return kAnimationInterval;
}
@end
...
//
// DataPickerPresenter.h
// ShowDatePickerView
//
// Created by Christopher John Morris on 10/11/13.
// Copyright (c) 2013 Christopher John Morris. All rights reserved.
//
#import "PickerPresenter.h"
@protocol DataPickerPresenterDelegate;
@interface UIPickerViewPresenter : PickerPresenter
/*
* Singleton instance of class
*/
+ (id) defaultPresenter;
/*
* Calls back to register button clicks
*/
@property (nonatomic, strong) id<DataPickerPresenterDelegate>delegate;
- (void) setDataArrayWithArray:(NSArray *)array;
@end
/*
* Delegate that is used to send messages from subclasses
* to classes using the subclass.
*/
@protocol DataPickerPresenterDelegate
@required
- (void) dataPickerPresenerClickedCancel:(UIPickerViewPresenter *)picker;
- (void) dataPickerPresenerClickedDone:(UIPickerViewPresenter *)picker withString:(NSString *)string index:(NSInteger)index;
@end
...
//
// DataPickerPresenter.m
// ShowDatePickerView
//
// Created by Christopher John Morris on 10/11/13.
// Copyright (c) 2013 Christopher John Morris. All rights reserved.
//
#import "UIPickerViewPresenter.h"
@interface UIPickerViewPresenter() <PickerPresenterButtonDelegate, UIPickerViewDelegate, UIPickerViewDataSource>
@property (nonatomic, strong) UIPickerView *picker;
@property (nonatomic, strong) NSArray *pickerData;
@end
@implementation UIPickerViewPresenter
+(id)defaultPresenter {
static UIPickerViewPresenter *defaultPresenter = nil;
if (!defaultPresenter) {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
defaultPresenter = [[super allocWithZone:NULL] init];
});
}
return defaultPresenter;
}
+ (id)allocWithZone:(NSZone *)zone {
return [self defaultPresenter];
}
- (id)copyWithZone:(NSZone *)zone {
return self;
}
- (id)init {
self = [super init];
if (self) {
[self initializePicker];
buttonDelegate = self;
}
return self;
}
- (void) initializePicker {
self.picker = [[UIPickerView alloc] init];
CGRect screenRect = [[UIScreen mainScreen] bounds];
CGRect frame = self.picker.frame;
frame.origin.y = frame.origin.y + self.navBarHeight;
frame.size.width = screenRect.size.width;
self.picker.frame = frame;
self.picker.delegate = self;
self.picker.dataSource = self;
[pickerContainer addSubview:self.picker];
}
-(void)didCancel {
if (self.hideOnCancelClicked) {
[self hide];
}
[self.delegate dataPickerPresenerClickedCancel:self];
}
-(void)didSave {
if (self.hideOnDoneClicked) {
[self hide];
}
NSInteger selectedRow = [self.picker selectedRowInComponent:0];
NSString *selection = [self.pickerData objectAtIndex:selectedRow];
[self.delegate dataPickerPresenerClickedDone:self withString:selection index:selectedRow];
}
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
}
-(NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {
return 1;
}
-(NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {
return self.pickerData.count;
}
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component {
return [self.pickerData objectAtIndex:row];
}
- (void)setDataArrayWithArray:(NSArray *)array {
self.pickerData = array;
[self.picker reloadAllComponents];
}
@end
To initialize it, write:
UIPickerViewPresenter *presenter = [UIPickerViewPresenter defaultPresenter];
[presenter setDataArrayWithArray:self.dataArray];
where 'self.dataArray' is the data you would like to use to populate the UIPickerView. To display it, call:
[presenter show];
Upvotes: 1
Reputation: 1466
When you have an UITableView
perhaps you can use this: https://github.com/aberger/ABMExpandingTableViewCells
Upvotes: 0