CNContactPickerViewController contact list offset issue - objective-c

Description: If I set "[[UIScrollView appearance] setContentInsetAdjustmentBehavior:UIScrollViewContentInsetAdjustmentNever];" somewhere else in my app, the first two items in CNContactPicerViewController will be coverd and cannot be touched. Setting UIScrollViewContentInsetAdjustmentAutomatic back before present Contact Picer will help the first two items to be touchable, but the initial position of the contact list is incorrect.
- (IBAction)chooseFromContact:(id)sender {
if (#available(iOS 11.0, *)){
[[UIScrollView appearance] setContentInsetAdjustmentBehavior:UIScrollViewContentInsetAdjustmentNever];
}
ContactManager *contactManager = [ContactManager sharedInstance];
[contactManager selectContactAtController:self complection:^(NSString * _Nonnull phone) {
NSLog(#"Hello World");
}];
}
// in ContactManager.m
- (void)selectContactAtController:(UIViewController *)controller
complection:(void (^)(NSString *))completcion {
if (#available(iOS 11.0, *)){
[[UIScrollView appearance] setContentInsetAdjustmentBehavior:UIScrollViewContentInsetAdjustmentAutomatic];
}
self.contactPicker = [[CNContactPickerViewController alloc] init];
self.contactPicker.delegate = self;
[controller presentViewController:self.contactPicker animated:YES completion:nil];
self.currentViewController = controller;
self.didselectPhone = completcion;
}
Expected result:
Actual result:

Related

TabBar with center button

Hi, I'd like to make a tabBar with center button. As we can see from the image, when I clicked the tabbar, it will show me a view to select buttons. When I clicked the "notes" button, the view will disappear and my app will jump to the correspond viewcontroller and the tabbar.selectIndex = 2. I already made a subclass of UITabBarController, and add a button to the view, the code is like this [self.view addSubview:middleButton]. Now the problem is, when I push viewcontroll, the tabbar disappear while the center button still on the page. And when I go back to the main viewcontroller, the tabbar will overlap the center button. I don't want to make a whole custom UITabBarViewController, please tell me how to hide the center button when push viewcontroll and how to show it on the tapbar when I go back to the main viewcontroller.
Hi, Hament, I have not use method "-(void)tabBar:(UITabBar *)tabBar didSelectItem:(UITabBarItem *)item". My code is as below:
#implementation MyTabBarController
- (void)viewDidLoad {
[super viewDidLoad];
[self setupViews];
[self setupTabBarItems];
[self setupMiddleButton];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(void)setupViews
{
mask = [[NSBundle mainBundle] loadNibNamed:NSStringFromClass([MyMiddleButtonMask class]) owner:self options:nil].firstObject;
mask.frame = CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
mask.delegate = self;
}
-(void)setupTabBarItems
{
UIViewController *vc1 = [[UIViewController alloc] init];
vc1Nav = [[UINavigationController alloc] initWithRootViewController:vc1];
UIViewController *vc2 = [[UIViewController alloc] init];
vc2Nav = [[UINavigationController alloc] initWithRootViewController:vc2];
UIViewController *vc3 = [[UIViewController alloc] init];
vc3Nav = [[UINavigationController alloc] initWithRootViewController:vc3];
UIViewController *vc6 = [[UIViewController alloc] init];
vc6Nav = [[UINavigationController alloc] initWithRootViewController:vc6];
UIViewController *vc7 = [[UIViewController alloc] init];
vc7Nav = [[UINavigationController alloc] initWithRootViewController:vc7];
self.viewControllers = #[vc1Nav, vc2Nav, vc3Nav, vc6Nav, vc7Nav];
}
-(void)setupMiddleButton
{
middleButton = [[UIButton alloc] initWithFrame:CGRectMake(0, -16, 64, 64)];
CGRect f = middleButton.frame;
f.origin.y = SCREEN_HEIGHT - f.size.height;
f.origin.x = (SCREEN_WIDTH - f.size.width)/2;
middleButton.frame = f;
[middleButton setImage:[UIImage imageNamed:#"plus"] forState:UIControlStateNormal];
middleButton.backgroundColor = [UIColor redColor];
middleButton.layer.cornerRadius = middleButton.frame.size.height/2;
[self.view addSubview:middleButton];
[middleButton addTarget:self action:#selector(didClickedMiddleButton:) forControlEvents:UIControlEventTouchUpInside];
}
-(void)didClickedMiddleButton:(id)sender
{
[[UIApplication sharedApplication].keyWindow.rootViewController.view addSubview:mask];
}
#pragma mark - KGOMiddleButtonMaskDelegate, Button1,2,3 are on the mask page.
-(void)didClickedButton1:(KGOMiddleButtonMask *)maskView
{
self.viewControllers = #[vc1Nav, vc2Nav, vc3Nav, vc6Nav, vc7Nav];
self.selectedIndex = 2;
[maskView removeFromSuperview];
}
-(void)didClickedButton2:(KGOMiddleButtonMask *)maskView
{
self.viewControllers = #[vc1Nav, vc2Nav, vc4Nav, vc6Nav, vc7Nav];
self.selectedIndex = 2;
[maskView removeFromSuperview];
}
-(void)didClickedButton3:(KGOMiddleButtonMask *)maskView
{
self.viewControllers = #[vc1Nav, vc2Nav, vc5Nav, vc6Nav, vc7Nav];
self.selectedIndex = 2;
[maskView removeFromSuperview];
}
-(void)didClickedSelf:(KGOMiddleButtonMask *)maskView
{
[maskView removeFromSuperview];
}
-(void)didClickedCloseButton:(KGOMiddleButtonMask *)maskView
{
[maskView removeFromSuperview];
}

UIRefreshControl incorrect title offset during first run and sometimes title missing

The text is offset wrong by the first launch of UIRefreshControl... later sometimes the refresh text doesn't show up at all and just the spiny is visible
I don't think i had this issue with iOS6... might be related to iOS7
Is in a UITableViewController added as a child to a VC, which resides in a modal presented UINavigationController
- (void)viewDidLoad {
[super viewDidLoad];
[self setRefreshControlText:#"Getting registration data"];
[self.refreshControl beginRefreshing];
}
- (void)setRefreshControlText:(NSString *)text {
UIFont * font = [UIFont fontWithName:#"Helvetica-Light" size:10.0];
NSDictionary *attributes = #{NSFontAttributeName:font, NSForegroundColorAttributeName : [UIColor blackColor]};
self.refreshControl.attributedTitle = [[NSAttributedString alloc] initWithString:text attributes:attributes];
}
This is definitely an iOS 7 bug, but I haven't figured out exactly what caused it. It appears to have something to do with the view hierarchy — adding my UITableViewController as a child view to a wrapper view controller appeared to fix it for me at first, although the bug is back since iOS 7 GM.
It looks like adding the following code to your UITableViewController after creating the refresh view fixes the positioning issue for good:
dispatch_async(dispatch_get_main_queue(), ^{
[self.refreshControl beginRefreshing];
[self.refreshControl endRefreshing];
});
calling endRefreshing under viewWillAppear did it for me:
-(void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self.refreshControl endRefreshing];
}
Under iOS7 with a custom UITableViewController inside a UINavigationController
I had the same problem and for me it worked with layoutIfNeeded after setting the attributedTitle:
- (void)setRefreshControlText:(NSString *)text
{
UIColor *fg = [UIColor colorWithWhite:0.4 alpha:1.0];
NSDictionary *attrsDictionary = #{NSForegroundColorAttributeName: fg};
self.refreshControl.attributedTitle = [[NSAttributedString alloc] initWithString:text attributes:attrsDictionary];
[self.refreshControl layoutIfNeeded];
}
Cédric suggested to use [self.refreshControl setNeedsLayout], but this does not force an immediate update of the view, so you must use layoutIfNeeded.
I finally found the holy grail on this, which looks working in all cases
note : UIRefreshControl is added to a UITableViewController (note, never add UIRefreshControl just as subview to a normal UIVIewController's UITableView) (best to add UITableViewController as a child VC inside a UIViewController if you must)
note : that this also fixes the problem, that the UIRefreshControl is not vissible at first refresh (link)
Add to you .h
#interface MyViewController ()
#property (nonatomic, assign) BOOL refreshControlFixApplied;
- (void)beginRefreshing;
- (void)beginRefreshingWithText:(NSString *)text;
- (void)endRefreshing;
- (void)endRefreshingWithText:(NSString *)text;
#end
Add to you .m
////////////////////////////////////////////////////////////////////////
#pragma mark - UIRefreshControl Fix (peter#min60.com) https://stackoverflow.com/questions/19121276/uirefreshcontrol-incorrect-title-offset-during-first-run-and-sometimes-title-mis/
////////////////////////////////////////////////////////////////////////
- (void)beginRefreshingWithText:(NSString *)text {
[self setRefreshControlText:text];
[self beginRefreshing];
}
- (void)endRefreshingWithText:(NSString *)text {
[self setRefreshControlText:text];
[self.refreshControl endRefreshing];
}
- (void)beginRefreshing {
if (self.refreshControl == nil) {
return;
}
if (!self.refreshControlFixApplied) {
dispatch_async(dispatch_get_main_queue(), ^{
if ([self.refreshControl.attributedTitle length] == 0) {
[self setRefreshControlText:#" "];
}
[self.refreshControl beginRefreshing];
dispatch_async(dispatch_get_main_queue(), ^{
[self.refreshControl endRefreshing];
dispatch_async(dispatch_get_main_queue(), ^{
// set the title before calling beginRefreshing
if ([self.refreshControl.attributedTitle length] == 0) {
[self setRefreshControlText:#" "];
}
if (self.tableView.contentOffset.y == 0) {
self.tableView.contentOffset = CGPointMake(0, -self.refreshControl.frame.size.height);
}
[self.refreshControl beginRefreshing];
self.refreshControlFixApplied = YES;
});
});
});
} else {
if (self.tableView.contentOffset.y == 0) {
self.tableView.contentOffset = CGPointMake(0, -self.refreshControl.frame.size.height);
}
[self.refreshControl beginRefreshing];
}
}
- (void)endRefreshing {
if (self.refreshControl == nil) {
return;
}
if (!self.refreshControlFixApplied) {
dispatch_async(dispatch_get_main_queue(), ^{
[self endRefreshing];
});
} else {
if (self.tableView.contentOffset.y < 0) {
self.tableView.contentOffset = CGPointMake(0, 0);
}
[self.refreshControl endRefreshing];
}
}
- (void)setRefreshControlText:(NSString *)text {
UIFont * font = [UIFont fontWithName:#"Helvetica-Light" size:10.0];
NSDictionary *attributes = #{NSFontAttributeName : font, NSForegroundColorAttributeName : [UIColor colorWithHex:0x00B92E]};
self.refreshControl.attributedTitle = [[NSAttributedString alloc] initWithString:text attributes:attributes];
}
Use only methods
- (void)beginRefreshing;
- (void)beginRefreshingWithText:(NSString *)text;
- (void)endRefreshing;
- (void)endRefreshingWithText:(NSString *)text;
UIRefreshControl seems to still be broken on IOS9.3 when you change the attributedTitle while the tableView is pulled down. What seems to work is to subclass UIRefreshControl and force update its layout once the (attributed) title is changed.
The core fix is to trigger a change to the tableView contentOffset (causing some hidden magic in the _update method which layouts the spinner and text subviews) and additionally forcing the frame height to its expected value ensuring the background color fills up the pulled down region.
#implementation MEIRefreshControl
{
__weak UITableView* _tableView;
}
- (instancetype)initWithTableView:(UITableView*)tableView
{
self = [super initWithFrame:CGRectZero];
if (self)
{
_tableView = tableView;
}
return self;
}
#synthesize title = _title;
- (void)setTitle:(NSString *)title
{
if (!PWEqualObjects(_title, title))
{
_title = title;
self.attributedTitle = [[NSAttributedString alloc] initWithString:_title ? _title : #""];
[self forceUpdateLayout];
}
}
- (void)forceUpdateLayout
{
CGPoint contentOffset = _tableView.contentOffset;
_tableView.contentOffset = CGPointZero;
_tableView.contentOffset = contentOffset;
CGRect frame = self.frame;
frame.size.height = -contentOffset.y;
self.frame = frame;
}
#end
This is the code that seems to fix all the issues. Many of the others that involved beginning or ending refreshing where interfering with other parts of the control.
//This chunk of code is needed to fix an iOS 7 bug with UIRefreshControls
static BOOL refreshLoadedOnce = NO;
if (!refreshLoadedOnce) {
__weak typeof(self) weakself = self;
[UIView animateWithDuration:0.25 delay:0 options:UIViewAnimationOptionBeginFromCurrentState animations:^(void){
self.tableView.contentOffset = CGPointMake(0, -weakself.refreshControl.frame.size.height);
} completion:^(BOOL finished) {
weakself.refreshControl.attributedTitle = self.refreshControl.attributedTitle;
[weakself.refreshControl setNeedsUpdateConstraints];
[weakself.refreshControl setNeedsLayout];
refreshLoadedOnce = YES;
}];
}
//End of bug fix
I had the same problem, I did solve it by setting attributed text with space string to refresh control directly after init refresh control
_refreshControl = [[UIRefreshControl alloc]init];
[_refreshControl setAttributedTitle:[[NSAttributedString alloc]initWithString:#" "]];
After that, setting new attributed text to refresh control was without any problems.
[[self refreshControl] setAttributedTitle:[[NSAttributedString alloc]initWithString:[NSString stringWithFormat:#"Последнее обновление: %#", [dateFormat stringFromDate:[_post dateUpdated]]]]];
UPDATE
I noticed that problem come back when I use attrsDictionary:
this code works fine
NSAttributedString* attributedString = [[NSAttributedString alloc]initWithString:string];
[[self refreshControl] setAttributedTitle: attributedString];
and this make refreshControl's title appear directly after view loaded
NSAttributedString* attributedString = [[NSAttributedString alloc]initWithString:string attributes:attrsDictionary];
[[self refreshControl] setAttributedTitle: attributedString];
I didn't find solution yet.
UPDATE
Finally found solution, after refreshcontrol init set attributed string also with attributes:attrsDictionary
NSDictionary *attrsDictionary = [NSDictionary dictionaryWithObjects:
[NSArray arrayWithObjects:[UIColor appDarkGray], [UIFont fontWithName:#"OpenSans-CondensedLight" size:14.0f], nil] forKeys:
[NSArray arrayWithObjects:NSForegroundColorAttributeName, NSFontAttributeName, nil]];
[_refreshControl setAttributedTitle:[[NSAttributedString alloc]initWithString:#" " attributes:attrsDictionary]];
so after that there is no problem to set new refreshcontrol's title.
The solution for me was to set a text in viewDidAppear, no need to call
beginRefreshing or endRefreshing on the mainQueue
-(void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:#"d MMM, HH:mm"];
NSString *lastUpdated = [NSString stringWithFormat:NSLocalizedString(#"refresh_last_updated", nil),[formatter stringFromDate:[NSDate dateWithTimeIntervalSince1970:[[[DatabaseController sharedInstance] getCurrentSettings].lastTimeStamp doubleValue]]]];
UIFont *font = [UIFont fontWithName:FONT_LATO_LIGHT size:12.0f];
NSAttributedString *attrString = [[NSAttributedString alloc] initWithString:lastUpdated attributes:#{NSFontAttributeName:font}];
_refreshControl.attributedTitle = attrString;
}

UITabbarItem BadgeValue Text Color

I have a problem in my App. I set a badge value at one of the tabs in the UITabBar. The Badge value is correctly red and the circle around the badge value is correctly in white. The problem is, that the color of the text is gray (160, 160, 160). It is the same color like the normal state tabbaritem text is, but I set this color nowhere in the app code and I do not know where this color come from.
I searched for that issue in the whole net since weeks but I cannot find any solution. The only answer I found everywhere is, that it is not possible to change the color of the text of the badge value. But if it is not possible, why is it changed in my app?
I hope, that somebody can help me with that issue...
http://www.luventas-webdesign.de/stackoverflow/screenshot_badgevalue.png
Like the color is in my app
http://www.luventas-webdesign.de/stackoverflow/screenshot_like_it_should.png
Like the color should normally be...
Edit 02.11.2012 - Code
Creation of TabBarController:
#import "ExtendedTabBarController.h"
#import "configuration.h"
#implementation ExtendedTabBarController
- (void)viewDidLoad {
[super viewDidLoad];
[[UITabBarItem appearance] setTitleTextAttributes:[NSDictionary dictionaryWithObjectsAndKeys: [UIColor colorWithRed:207.0/255.0 green:70.0/255.0 blue:61.0/255.0 alpha:1], UITextAttributeTextColor, [UIFont fontWithName:#"KievitPro-Regular" size:10.0], UITextAttributeFont, nil] forState:UIControlStateSelected];
[[UITabBarItem appearance] setTitleTextAttributes:[NSDictionary dictionaryWithObjectsAndKeys: [UIColor colorWithRed:255.0/255.0 green:255.0/255.0 blue:255.0/255.0 alpha:1], UITextAttributeTextColor, [UIFont fontWithName:#"KievitPro-Regular" size:10.0], UITextAttributeFont, nil] forState:UIControlStateNormal];
[self.tabBar sizeToFit];
UIView *tabbarBackgroundColorView = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0, self.view.bounds.size.width, 49)];
[tabbarBackgroundColorView setBackgroundColor:[UIColor colorWithRed:233.0/255.0 green:233.0/255.0 blue:233.0/255.0 alpha:1]];
[self.tabBar insertSubview:tabbarBackgroundColorView atIndex:0];
}
- (void)viewDidUnload {
[super viewDidUnload];
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return UIInterfaceOrientationIsPortrait(interfaceOrientation); // only portrait orientation
}
/**
* orientation for iOS6
**/
-(NSUInteger)supportedInterfaceOrientations{
return UIInterfaceOrientationMaskPortrait;
}
#end
Call in AppDelegate:
ExtendedTabBarController *tabBarController = [[ExtendedTabBarController alloc] init];
[self setTabBarController:tabBarController];
[[UITabBar appearance] setBackgroundImage:[UIImage imageNamed:#"menu_bg"]];
// code for initialize View- and NavigationControllers...
self.tabBarController.viewControllers = #[highlightsNavigationController, categoryNavigationController, searchNavigationController, favoritesNavigationController, imprintNavigationController];
self.window.rootViewController = self.tabBarController;
[[UITabBar appearance] setSelectionIndicatorImage:[[UIImage alloc] init]];
Set the badge value:
int viewCount = 0;
NSUserDefaults * defs = [NSUserDefaults standardUserDefaults];
NSDictionary * dict = [defs dictionaryRepresentation];
for (id key in dict) {
if([key rangeOfString:#"_highlighted"].location != NSNotFound && [[[dict objectForKey:key] objectAtIndex:0] isEqualToString:#"YES"]) {
viewCount++;
}
}
UITabBarItem *tbi = (UITabBarItem *)[self.tabBarController.tabBar.items objectAtIndex:3];
if(viewCount <= 0) {
tbi.badgeValue = nil;
} else {
tbi.badgeValue = nil;
tbi.badgeValue = [NSString stringWithFormat:#"%d", viewCount];
}
Code for overwritten UILabel:
// -- file: UILabel+VerticalAlign.h
#pragma mark VerticalAlign
#interface UILabel (VerticalAlign)
- (void)alignTop;
- (void)alignBottom;
- (void)awakeFromNib;
-(id)initWithFrame:(CGRect)frame;
#end
#import "UILabel+VerticalAlign.h"
// -- file: UILabel+VerticalAlign.m
#implementation UILabel (VerticalAlign)
- (void)alignTop {
CGSize fontSize = [self.text sizeWithFont:self.font];
double finalHeight = fontSize.height * self.numberOfLines;
double finalWidth = self.frame.size.width; //expected width of label
CGSize theStringSize = [self.text sizeWithFont:self.font constrainedToSize:CGSizeMake(finalWidth, finalHeight) lineBreakMode:self.lineBreakMode];
int newLinesToPad = (finalHeight - theStringSize.height) / fontSize.height;
for(int i=0; i<newLinesToPad; i++)
self.text = [self.text stringByAppendingString:#"\n "];
}
- (void)alignBottom {
CGSize fontSize = [self.text sizeWithFont:self.font];
double finalHeight = fontSize.height * self.numberOfLines;
double finalWidth = self.frame.size.width; //expected width of label
CGSize theStringSize = [self.text sizeWithFont:self.font constrainedToSize:CGSizeMake(finalWidth, finalHeight) lineBreakMode:self.lineBreakMode];
int newLinesToPad = (finalHeight - theStringSize.height) / fontSize.height;
for(int i=0; i<newLinesToPad; i++)
self.text = [NSString stringWithFormat:#" \n%#",self.text];
}
- (void)awakeFromNib
{
[super awakeFromNib];
[self setFont:[UIFont fontWithName:#"KievitPro-Regular" size:12.0]];
}
-(id)initWithFrame:(CGRect)frame
{
id result = [super initWithFrame:frame];
if (result) {
[self setFont:[UIFont fontWithName:#"KievitPro-Regular" size:12.0]];
}
return result;
}
#end
I found a solution for my problem on my own:
I must remove the following lines from the overwritten UILabel:
- (void)awakeFromNib
{
[super awakeFromNib];
[self setFont:[UIFont fontWithName:#"KievitPro-Regular" size:12.0]];
}
-(id)initWithFrame:(CGRect)frame
{
id result = [super initWithFrame:frame];
if (result) {
[self setFont:[UIFont fontWithName:#"KievitPro-Regular" size:12.0]];
}
return result;
}
Maybe someone can explain me, why this lines change the text color of the badge value, before we can close this post?
Instead of setting the default UILabel font using a category, use the UILabel's appearance method to set the font:
[[UILabel appearance] setFont:[UIFont fontWithName:#"KievitPro-Regular" size:12.0]];
When I tested this the text for the badge appeared as the normal white color.

How to display imagepickercontroller through popoverview controller?

I have used the following code to get photos from album in iphone but it displays the error "UIImagePickerController must be presented via UIPopoverController"
- (void)showImagePicker:(UIImagePickerControllerSourceType)sourceType
{
if ([UIImagePickerController isSourceTypeAvailable:sourceType])
{
[self setupImagePicker:sourceType];
[self presentModalViewController:imagePickerController animated:YES];
}
}
- (void)setupImagePicker:(UIImagePickerControllerSourceType)sourceType
{
imagePickerController.sourceType = sourceType;
if (sourceType == UIImagePickerControllerSourceTypeCamera)
{
// user wants to use the camera interface
//
imagePickerController.showsCameraControls = NO;
if (imagePickerController.cameraOverlayView != self.view)
{
// setup our custom overlay view for the camera
//
// ensure that our custom view's frame fits within the parent frame
CGRect overlayViewFrame = imagePickerController.cameraOverlayView.frame;
CGRect newFrame = CGRectMake(0.0,
CGRectGetHeight(overlayViewFrame) -
self.view.frame.size.height - 9.0,
CGRectGetWidth(overlayViewFrame),
self.view.frame.size.height + 9.0);
self.view.frame = newFrame;
imagePickerController.cameraOverlayView = self.view;
}
}
}
-(IBAction)getPhoto:(id)sender {
imagePickerController = [[UIImagePickerController alloc] init];
[self showImagePicker:UIImagePickerControllerSourceTypePhotoLibrary];
}
Can any one please alter my code to work on iPad.
Thanks in advance.
-(IBAction)Click_event
{
UIImagePickerController *imagePickerController_=[[UIImagePickerController alloc] init];
UIPopoverController *popover_=[[UIPopoverController alloc] initWithContentViewController:imagePickerController_];
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]) {
imagePickerController_.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
[popover_ presentPopoverFromRect:CGRectMake(400, 400, 0, 0) inView:self.Mybutton
permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}
}

UIPickerView with a Done button in Ipad

I have faced one issue to display UIPickerView with a Done button in Ipad.
I done detailed researches though many links and blogs and got the suggestion as "display the UIPickerView from an UIActionSheet"
I saw many posts related this, however there is no good answers.So please dont close it as a duplicate.
Also i was able to get some good codes to do it and it worked fine in my Iphone devices.
However i were found a difficulty in Ipad devices.
The Action-Sheet is not displaying as a full view.
Please see the below screenshot.this was the result!!!
The code is used to do this is pasted below.
UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:nil
delegate:nil
cancelButtonTitle:nil
destructiveButtonTitle:nil
otherButtonTitles:nil];
[actionSheet setActionSheetStyle:UIActionSheetStyleBlackTranslucent];
CGRect pickerFrame = CGRectMake(0, 40, 0, 0);
UIPickerView *pickerView = [[UIPickerView alloc] initWithFrame:pickerFrame];
pickerView.showsSelectionIndicator = YES;
pickerView.dataSource = self;
pickerView.delegate = self;
[actionSheet addSubview:pickerView];
[pickerView release];
UISegmentedControl *closeButton = [[UISegmentedControl alloc] initWithItems:[NSArray arrayWithObject:#"Close"]];
closeButton.momentary = YES;
closeButton.frame = CGRectMake(260, 7.0f, 50.0f, 30.0f);
closeButton.segmentedControlStyle = UISegmentedControlStyleBar;
closeButton.tintColor = [UIColor blackColor];
[closeButton addTarget:self action:#selector(dismissActionSheet:) forControlEvents:UIControlEventValueChanged];
[actionSheet addSubview:closeButton];
[closeButton release];
[actionSheet showInView:[[UIApplication sharedApplication] keyWindow]];
[actionSheet setBounds:CGRectMake(0, 0, 320, 485)];
Then I have downloaded a excellent sample application from github through sample pickers
After the download, i have copied the classes only mandatory for me to my application.
The method they are using to show the UIPickerView+Done button through Action-Sheet is described below
ActionStringDoneBlock done = ^(ActionSheetStringPicker *picker, NSInteger selectedIndex, id selectedValue) {
if ([myLabel respondsToSelector:#selector(setText:)]) {
[myLabel performSelector:#selector(setText:) withObject:selectedValue];
}
};
ActionStringCancelBlock cancel = ^(ActionSheetStringPicker *picker) {
NSLog(#"Block Picker Canceled");
};
NSArray *colors = [NSArray arrayWithObjects:#"Red", #"Green", #"Blue", #"Orange", nil];//picker items to select
[ActionSheetStringPicker showPickerWithTitle:#"Select a Block" rows:colors initialSelection:0 doneBlock:done cancelBlock:cancel origin:myButton];
In the last line of code they have used the parameter as origin: and we can pass any objects (button,label etc) to it.
The Action-sheet will take origin as the passed object.
Here my issue came again :). I have used segment control to pick the time as per my conditions.
if i give mySegment as the origin parameter,the Action-sheet origin arrow will display from middle of my segment control.Not from the selected tab ,which is too bad and will give confusion to my valuable users.
So i have added individual labels under the segment sections and given it for the origin parameter of the mentioned method and i fixed my issue.
However i know its not a good fix :)
May i know is there any easy way to do it?
Is Apple support ActionSheet+UIPickerView+DoneButton in Ipad?
Any help on this issue is Appreciated
-(void)viewDidload
{
UIButton *button1 = [UIButton buttonWithType:UIButtonTypeRoundedRect];
button1.frame = CGRectMake(165,165, 135,35);
[button1 setTitle:#"Type #" forState:UIControlStateNormal];
[button1 addTarget:self action:#selector(button1) forControlEvents:UIControlEventTouchUpInside];
[s addSubview:button1];
}
-(void)button1
{
items1 =[[NSMutableArray alloc]initWithObjects:#"H",#"E",#"T",#"K",nil];
myPickerView1 =[[UIPickerView alloc] initWithFrame:CGRectMake(60,80,200,300)];
myPickerView1.transform = CGAffineTransformMakeScale(0.75f, 0.75f);
myPickerView1.delegate = self;
myPickerView1.dataSource = self;
myPickerView1.showsSelectionIndicator = YES;
myPickerView1.backgroundColor = [UIColor clearColor];
myPickerView1.tag=1;
[myPickerView1 selectRow:1 inComponent:0 animated:YES];
[self.view addSubview:myPickerView1];
}
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView;
{
return 1;
}
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component;
{
switch (pickerView.tag)
{
case 1:
return [items1 count];
break;
case 2:
return [items2 count];
break;
}
return 0;
}
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
{
switch (pickerView.tag)
{
case 1:
return[items1 objectAtIndex:row];
break;
case 2:
return[items2 objectAtIndex:row];
break;
}
return 0;
}
-(void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
switch (pickerView.tag)
{
case 1:
{
[button1 setTitle:[items1 objectAtIndex:row] forState:UIControlStateNormal];
}
break;
case 2:
{
[button2 setTitle:[items2 objectAtIndex:row] forState:UIControlStateNormal];
}break;
}
pickerView.hidden = YES;
}
You have to use UIPopOverController.
First, create a UIPickerViewController for iPhone. You need it for the nib, which will be pushed into the popOver. Initialize the picker in ViewWithPicker
.h
#import <UIKit/UIKit.h>
#class ViewWithPickerController;
#protocol PopoverPickerDelegate
#required
- (void) viewWithPickerController:(ViewWithPickerController*) viewWithPickerController didSelectValue:(NSString*) value;
#end
#interface ViewWithPickerController : UIViewController <UIPickerViewDelegate, UIPickerViewDataSource> {
IBOutlet UIPickerView *pickerView;
id<PopoverPickerDelegate> delegate;
NSMutableArray *array;
}
#property(nonatomic, retain) IBOutlet UIPickerView *pickerView;
#property(nonatomic, assign) id<PopoverPickerDelegate> delegate;
#end
.m, after you initialized the array in viewDidLoad, picker methods:
// returns the number of 'columns' to display.
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)picker {
return 1;
}
// returns the number of rows in each component.
- (NSInteger)pickerView:(UIPickerView *)picker numberOfRowsInComponent:(NSInteger)component {
return [array count];
}
//returns the string value for the current row
- (NSString *)pickerView:(UIPickerView *)picker titleForRow:(NSInteger)row forComponent:(NSInteger)component {
return [array objectAtIndex:row];
}
//handle selection of a row
- (void)pickerView:(UIPickerView *)picker didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
NSString *value = [pickerView.delegate pickerView:picker titleForRow:row forComponent:component];
//notify the delegate about selecting a value
if(delegate != nil)
[delegate viewWithPickerController:self didSelectValue:value];
}
Then, import the viewWithPicker into your main class, create a button and give it this action:
- (IBAction) showPickerPopupAction:(id) sender {
self.viewWithPickerController = [[[ViewWithPickerController alloc] initWithNibName:#"ViewWithPicker" bundle:[NSBundle mainBundle]] autorelease];
viewWithPickerController.contentSizeForViewInPopover =
CGSizeMake(viewWithPickerController.view.frame.size.width, viewWithPickerController.view.frame.size.height);
viewWithPickerController.delegate = self;
self.popoverController = [[[UIPopoverController alloc]
initWithContentViewController:viewWithPickerController] autorelease];
[self.popoverController presentPopoverFromRect:popoverButtonForPicker.frame inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
popoverController.delegate = self;
}
And to select a specific value
- (void) viewWithPickerController:(ViewWithPickerController*) viewWithPickerController didSelectValue:(NSString*) value
{
yourLabel.text = [NSString stringWithFormat:#"%# ",value];
}
Use UIPopoverController for done button in picker, create a view controller class in which take a picker and add navigation cancel and done button.
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:nextViewController];
_datePickerPopover = [[UIPopoverController alloc] initWithContentViewController:navigationController];
nextViewController.datePickerPopover = _datePickerPopover;
_datePickerPopover.delegate=self;
[_datePickerPopover setPopoverContentSize:CGSizeMake(320, 453) animated:NO];
if (isSearchOpen) {
[_datePickerPopover presentPopoverFromRect:CGRectMake(btn.frame.origin.x+10+245, btn.frame.origin.y+100-scrollPointY, 44, 44) inView:self.splitViewController.view permittedArrowDirections:UIPopoverArrowDirectionLeft animated:YES];
}
else
{
[_datePickerPopover presentPopoverFromRect:CGRectMake(btn.frame.origin.x+10+245, btn.frame.origin.y+55, 44, 44) inView:self.splitViewController.view permittedArrowDirections:UIPopoverArrowDirectionLeft animated:YES];//
}
Try out below code for UIPicker View in iPad
-(IBAction)tDriveBtnPressed:(id)sender
{
NSDateFormatter *df = [[NSDateFormatter alloc] init];
df.dateStyle = NSDateFormatterMediumStyle;
txtDate.text = [NSString stringWithFormat:#"%#",
[df stringFromDate:[NSDate date]]];
[df release];
UIToolbar *pickerToolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0, 0, 300, 44)];
pickerToolbar.barStyle = UIBarStyleBlackOpaque;
[pickerToolbar sizeToFit];
NSMutableArray *barItems = [[NSMutableArray alloc] init];
UIBarButtonItem *doneBtn = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:#selector(pickerDone:)];
[barItems addObject:doneBtn];
[doneBtn release];
[pickerToolbar setItems:barItems animated:YES];
[barItems release];
datePicker = [[UIDatePicker alloc] init];
datePicker.datePickerMode = UIDatePickerModeDate;
CGRect pickerRect = datePicker.bounds;
datePicker.bounds = pickerRect;
UIViewController* popoverContent = [[UIViewController alloc] init];
UIView* popoverView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 344)];
popoverView.backgroundColor = [UIColor whiteColor];
datePicker.frame = CGRectMake(0, 44, 320, 300);
[datePicker addTarget:self action:#selector(dateChange:) forControlEvents:UIControlEventValueChanged];
[popoverView addSubview:pickerToolbar];
[popoverView addSubview:datePicker];
popoverContent.view = popoverView;
//resize the popover view shown
//in the current view to the view's size
popoverContent.contentSizeForViewInPopover = CGSizeMake(320, 244);
//create a popover controller
popoverController = [[UIPopoverController alloc] initWithContentViewController:popoverContent];
CGRect popoverRect = [self.view convertRect:[tDriveBtn frame]
fromView:[tDriveBtn superview]];
popoverRect.size.width = MIN(popoverRect.size.width, 100) ;
popoverRect.origin.x = popoverRect.origin.x;
// popoverRect.size.height = ;
[popoverController
presentPopoverFromRect:popoverRect
inView:self.view
permittedArrowDirections:UIPopoverArrowDirectionAny
animated:YES];
//release the popover content
[popoverView release];
[popoverContent release];
}
-(void)dateChange:(id)sender
{
NSDateFormatter *df = [[NSDateFormatter alloc] init];
df.dateStyle = NSDateFormatterMediumStyle;
txtDate.text= [NSString stringWithFormat:#"%#",
[df stringFromDate:datePicker.date]];
[df release];
}
- (void)pickerDone:(id)sender
{
NSDateFormatter *df = [[NSDateFormatter alloc] init];
df.dateStyle = NSDateFormatterMediumStyle;
txtDate.text= [NSString stringWithFormat:#"%#",
[df stringFromDate:datePicker.date]];
[df release];
if (popoverController != nil) {
[popoverController dismissPopoverAnimated:YES];
self.popoverController=nil;
}
}