UIPickerView on UIActionSheet in landscape mode appears blacked out - objective-c

I have an app the I update a table row through a UIActionSheet. On the sheet I present a UIPickerView. The UIPickerView works and looks great in portrait on the iphone. But when I bring it up in landscape mode, it still works, but the outline area appears black And unselected numbers are black also.
Below is a screenshot and code. Is there anything obviously wrong?
// create enough space for the UIPicker to show up above the selection button
NSString *title = #"\n\n\n\n\n\n\n\n\n\n\n\n";
if ((UIDeviceOrientationIsLandscape([UIDevice currentDevice].orientation)) &&
(UI_USER_INTERFACE_IDIOM() != UIUserInterfaceIdiomPad)) {
title = #"\n\n\n\n\n\n\n\n\n";
}
UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:title delegate:self cancelButtonTitle:nil destructiveButtonTitle:nil otherButtonTitles:NSLocalizedString(#"Choose", #"Click to finilize Value - Timer"), nil];
[actionSheet showInView:viewController.view];
UIDatePicker *pickerView = [[UIDatePicker alloc] init];
[pickerView setDatePickerMode: UIDatePickerModeCountDownTimer];
if (timerInterval == 0) timerInterval = 5;
[pickerView setMinuteInterval: timerInterval];
[pickerView setCountDownDuration: [timerRec.timerDuration intValue]];
pickerView.tag = 101;
if ((UIDeviceOrientationIsLandscape([UIDevice currentDevice].orientation)) &&
(UI_USER_INTERFACE_IDIOM() != UIUserInterfaceIdiomPad)) {
pickerView.frame = CGRectMake(0,0, 50,50);
}
//pickerView.delegate = self;
//pickerView.dataSource = self;
//ickerView.showsSelectionIndicator = YES;
[actionSheet addSubview:pickerView];

Related

iOS 8 UIActivityViewController and/or UIPopoverController are not dissmissed when clicked outside of them

I have read the UIPopoverController docs and more then 10 stackoverflow solutions which none work in iOS 8.0.2 ipad device.
THE GOAL:
I want to present a sharing view which when clicked outside dissmisses.
THE PROBLEM:
The code works fine below iOS 8.0.
THE CODE (tried many versions...):
NSArray *dataToShare = #[url]; // ...or whatever pieces of data you want to share.
UIActivityViewController* activityViewController =
[[UIActivityViewController alloc] initWithActivityItems:dataToShare
applicationActivities:nil];
activityViewController.modalInPopover = YES;
self.act = [[UIPopoverController alloc] initWithContentViewController:activityViewController];
[self.act presentPopoverFromRect:CGRectMake(self.view.bounds.size.width/2, self.view.bounds.size.height/2, self.view.bounds.size.width/2, self.view.bounds.size.width/2) inView:self.view permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];
self.act.delegate = self;
I have added the :
UIPopoverControllerDelegate
WHAT I HAVE TRIED:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
As soon that the
UIPopoverController
is presented the view losses focus and doesn't register touches. Therefore, I can't handle touches outside the self.act rect space in order to force a dissmisal.
also...
NSArray *dataToShare = #[url]; // ...or whatever pieces of data you want to share.
UIActivityViewController* activityViewController =
[[UIActivityViewController alloc] initWithActivityItems:dataToShare
applicationActivities:nil];
activityViewController.modalInPopover = YES;
UIPopoverPresentationController *presentationController = [activityViewController popoverPresentationController];
presentationController.sourceView = self.view; // if button or change to self.view.
[self.parentViewController presentViewController:activityViewController animated:YES completion:nil];
and I tried to present the UIActivityViewController and UIPopoverController from the parent which didn't work aswell.
Please help, I lost half day on something this stupid which works on iOS 7.1 and not on iOS 8+ which is ridiculous and I still have no clue why.
I will try to add the cancel button which has also disappeared in iOS8+.
UPDATE 1:
Adding a UIButton inside a UIBarButtonItem didn't help...
UIButton *control = (UIButton *) sender;
[control setFrame:CGRectMake(300, 300, 100, 100)];
[control setBackgroundColor:[UIColor redColor]];
UIBarButtonItem *barButtonItemView = [[UIBarButtonItem alloc] init];
[barButtonItemView setCustomView:control];
[self.popup presentPopoverFromBarButtonItem:barButtonItemView permittedArrowDirections:UIPopoverArrowDirectionRight animated:YES];
UPDATE 2 - 19.12.2014. (iOS 7.1. - 8.1.2):
The accepted answer works on iOS 8.1. I had some errors with iOS 7.1. so I modified it to work for iOS 7.1. I have stated on which devices the code works in the comments below the answer.
// publish - sharing
NSArray *dataToShare = #[url]; // ...or whatever pieces of data you want to share.
UIActivityViewController* activityViewController =
[[UIActivityViewController alloc] initWithActivityItems:dataToShare
applicationActivities:nil];
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
{
NSLog(#" SHARING - 1 - ");
[self presentViewController:activityViewController animated:YES completion:^{}];
}
else
{
// Change Rect to position Popover
NSLog(#" SHARING - 2 - ");
self.popup = [[UIPopoverController alloc] initWithContentViewController:activityViewController];
[self.popup presentPopoverFromRect:CGRectMake(self.view.frame.size.width * 3 / 5 ,
self.view.frame.size.width/2,
self.view.frame.size.width/10,
self.view.frame.size.width/10) inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}
How about just add this.
UIActivityViewController* activityViewController =
[[UIActivityViewController alloc] initWithActivityItems:dataToShare
applicationActivities:nil];
activityViewController.modalInPopover = YES;
activityViewController.popoverPresentationController.sourceView = self.view;

How do I remove or stop a button in table view from working after registered amount of taps

I have a button in a table view that adds rows. After a maximum of five rows I want to stop the user adding anymore. Currently I show an alert after button recives 5 taps.
How can I stop the user from using the button past this point? Setting to hidden wont work as its a custom subclass and property hidden is not found on the class
- (void)viewDidLoad
{
[super viewDidLoad];
UILabel *titleLabel = [[UILabel alloc] initWithFrame:CGRectZero];
titleLabel.backgroundColor = [UIColor clearColor];
titleLabel.textColor = [UIColor whiteColor];
titleLabel.shadowColor = [UIColor darkGrayColor];
titleLabel.text = self.distributionBoard.dbRef;
titleLabel.font = [UIFont boldSystemFontOfSize:15.0f];
[titleLabel sizeToFit];
self.navigationItem.titleView = titleLabel;
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:#selector(doneButtonPressed:)];
// Add new appliance button to the table view's footer view
UIView *footerView = [[UIView alloc] initWithFrame:CGRectMake(10.0f, 0, 300.0f, 100.0f)];
footerView.backgroundColor = [UIColor clearColor];
UIButton *newBoardButton = [UIButton buttonWithType:UIButtonTypeContactAdd];
CGRect buttonFrame = newBoardButton.frame;
buttonFrame.origin.x = footerView.frame.size.width - buttonFrame.size.width;
newBoardButton.frame = buttonFrame;
[newBoardButton addTarget:self action:#selector(addCircuitButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
[footerView addSubview:newBoardButton];
self.tableView.tableFooterView = footerView;
}
.....
////limit to five appliances
- (void)addCircuitButtonPressed:(id)sender {
LogCmd();
Circuit *circuit = [[ICCircuitManager manager] newCircuit];
circuit.distributionBoard = self.distributionBoard;
circuit.circuitReference = [NSString stringWithFormat:#"%d", [self.circuits count] + 1];
circuit.createdAt = [NSDate date];
circuit.modifiedAt = [NSDate date];
[self.distributionBoard addCircuitsObject:circuit];
[self loadData];
[self.tableView reloadData];
{
m_buttonTouchCount++;
if ( m_buttonTouchCount == 4)
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"iCertifi"
message:#"Maximum number of appliances reached"
delegate:nil
cancelButtonTitle:#"Ok"
otherButtonTitles:nil];
[alert show];
// m_buttonTouchCount = 0; // reset to 0 here if required.
}
}
}
Where you have AlertView you can type this code to disable button:
[(UIButton *)sender setEnabled:NO];
or to hide button:
[(UIButton *)sender setHidden:YES];

Black Bar in UIImagePicker on iPad - Only in Landscape Right Orientation

I am showing a UIImagePicker (itself in a UIView) via a UIPopOver. This works fine, however when the iPad is rotated onto its right side I get a strange black bar along the left hand side of the popover as per the image below. The cancel button is also partially off the right hand of the screen. This doesn't happen in any other orientation which is odd.
The code is also listed below. Can anyone suggest why I am getting this black bar ?
imagePickerController = [[UIImagePickerController alloc] init];
imagePickerController.delegate = self;
imagePickerController.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
CGFloat width = CGRectGetWidth(self.view.bounds);
CGFloat height = CGRectGetHeight(self.view.bounds);
UIViewController *containerController = [[UIViewController alloc] init];
containerController.contentSizeForViewInPopover = CGSizeMake(width, height);
[imagePickerController.view setFrame:containerController.view.frame];
[containerController.view addSubview:imagePickerController.view];
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
Class cls = NSClassFromString(#"UIPopoverController");
if (cls != nil) {
popoverController = [[UIPopoverController alloc] initWithContentViewController:containerController];
[popoverController presentPopoverFromRect:selectedRect inView:self.view permittedArrowDirections:4 animated:YES];
[containerController release];
}
For some strange reason, the view's frame does change in landscape right.
To come over this, set the frame after you present the popover (view code below).
That should do the trick.
imagePickerController = [[UIImagePickerController alloc] init];
imagePickerController.delegate = self;
imagePickerController.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
CGFloat width = CGRectGetWidth(self.view.bounds);
CGFloat height = CGRectGetHeight(self.view.bounds);
UIViewController *containerController = [[UIViewController alloc] init];
containerController.contentSizeForViewInPopover = CGSizeMake(width, height);
[containerController.view addSubview:imagePickerController.view];
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
Class cls = NSClassFromString(#"UIPopoverController");
if (cls != nil) {
popoverController = [[UIPopoverController alloc] initWithContentViewController:containerController];
[popoverController presentPopoverFromRect:selectedRect inView:self.view permittedArrowDirections:4 animated:YES];
[imagePickerController.view setFrame:containerController.view.frame];
[containerController release];
}
Also, in your controller, add this to reset the frames when the rotation occurs:
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
[imagePickerController.view setFrame:imagePickerController.view.superview.frame];
}
The above approach works with iOS 5 and above but on iOS 4 and prior it's not possible to add the UIImagePickerController as a subview and then show it. It always has to be presented as a ModalViewController.
Try this. Reposting one solution I found using [currentDevice endGeneratingDeviceOrientationNotifications]
UIImagePickerController *picker = [[[UIImagePickerController alloc] init] autorelease];
picker.sourceType = UIImagePickerControllerSourceTypeCamera;
picker.delegate = self;
// Display the camera.
[self presentModalViewController:picker animated:YES];
// Given by default your orientation is in landscape right already
while ([currentDevice isGeneratingDeviceOrientationNotifications])
[currentDevice endGeneratingDeviceOrientationNotifications];
Source: Disable rotation in UIImagePicker

Custom AlertView With Background

Everybody, I need to set one image on UIAlertView..
I have attached my UIAlertview with image prob..
i have used this code lines..
UIAlertView *theAlert = [[[UIAlertView alloc] initWithTitle:#"Atention"
message: #"YOUR MESSAGE HERE", nil)
delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil] autorelease];
[theAlert show];
UILabel *theTitle = [theAlert valueForKey:#"_titleLabel"];
[theTitle setTextColor:[UIColor redColor]];
UILabel *theBody = [theAlert valueForKey:#"_bodyTextLabel"];
[theBody setTextColor:[UIColor blueColor]];
UIImage *theImage = [UIImage imageNamed:#"Background.png"];
theImage = [theImage stretchableImageWithLeftCapWidth:16 topCapHeight:16];
CGSize theSize = [theAlert frame].size;
UIGraphicsBeginImageContext(theSize);
[theImage drawInRect:CGRectMake(0, 0, theSize.width, theSize.height)];
theImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
[[theAlert layer] setContents:[theImage CGImage]];
please solve this issue..
i need only image with alert..
Try this...
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"UIAlert View" message:#"hello" delegate:self cancelButtonTitle:#"OK" otherButtonTitles:#"Close",nil];
UIImage *alertImage = [UIImage imageNamed:#"plus.png"];
UIImageView *backgroundImageView = [[UIImageView alloc] initWithImage:alertImage];
backgroundImageView.frame = CGRectMake(0, 0, 282, 130);
backgroundImageView.contentMode = UIViewContentModeScaleToFill;
[alert addSubview:backgroundImageView];
[alert sendSubviewToBack:backgroundImageView];
[alert show];
[alert release];
You should consider to not use UIAlertView, but have your own AlertView see TSAlertView for an alternative implementation, that is not derived from UIAlertView.
TSAlertView is allowing you to set your own background image.
Another solution that I am not recommending could be:
You can use introspection: Loop over the UIAlertViews subviews, identify the one that holds the background image set it hidden and place your own backroundimage at an index below/over the original image view.
I found this project: Subclass UIAlertView to customize the look of an alert. It is not working for iOS 4.2+, but with my introspection idea you can make it work again:
change the -layoutSubviews of JKCustomAlert to:
- (void) layoutSubviews {
for (UIView *v in [self subviews]) {
if ([v class] == [UIImageView class]) {
[v setHidden:YES];
}
}
alertTextLabel.transform = CGAffineTransformIdentity;
[alertTextLabel sizeToFit];
CGRect textRect = alertTextLabel.frame;
textRect.origin.x = (CGRectGetWidth(self.bounds) - CGRectGetWidth(textRect)) / 2;
textRect.origin.y = (CGRectGetHeight(self.bounds) - CGRectGetHeight(textRect)) / 2;
textRect.origin.y -= 30.0;
alertTextLabel.frame = textRect;
alertTextLabel.transform = CGAffineTransformMakeRotation(- M_PI * .08);
}
I am NOT promising, that this trick will work in future versions of iOS
A solution I like to use for this is to add a UIView to the ViewController, which mimics the appearance of an alert.
The other property of a UIAlertView is that no other part of the app can be used until the alert is dismissed. This can easily be mimicked by making your UIView a subview of another UIView (with a clear background), which takes up the entire screen.
If you don't want to implement that yourself, here's a Custom Alert View class you could use: https://github.com/shivsak/CustomAlertView

Fitting a UIDatePicker into a UIActionSheet

I'm trying to get a UIDatePicker with a UIButton to show up in a UIActionSheet. Unfortunately it gets cropped off and the entire Date Picker is not visible. I have not even attempted to add the UIButton yet. Can anyone suggest on getting the entire view to fit properly? I'm not sure how to add the proper dimensions as UIActionSheet seems to lack an -initWithFrame: type constructor.
UIActionSheet *menu = [[UIActionSheet alloc] initWithTitle:#"Date Picker"
delegate:self
cancelButtonTitle:#"Cancel"
destructiveButtonTitle:nil
otherButtonTitles:nil];
// Add the picker
UIDatePicker *pickerView = [[UIDatePicker alloc] init];
pickerView.datePickerMode = UIDatePickerModeDate;
[menu addSubview:pickerView];
[menu showInView:self.view];
[pickerView release];
[menu release];
I've also tried with something similar to:
UIActionSheet *menu = [[UIActionSheet alloc] initWithFrame:CGRectMake(200.0, 200.0, 100.0f, 100.0f)];
The coords are ofcourse not realistic, but they don't seem to affect the position/size of the UIActionSheet.
You can use something like this (adjust the coordinates):
UIActionSheet *menu = [[UIActionSheet alloc] initWithTitle:#"Date Picker"
delegate:self
cancelButtonTitle:#"Cancel"
destructiveButtonTitle:nil
otherButtonTitles:nil];
// Add the picker
UIDatePicker *pickerView = [[UIDatePicker alloc] init];
pickerView.datePickerMode = UIDatePickerModeDate;
[menu addSubview:pickerView];
[menu showInView:self.view];
[menu setBounds:CGRectMake(0,0,320, 500)];
CGRect pickerRect = pickerView.bounds;
pickerRect.origin.y = -100;
pickerView.bounds = pickerRect;
[pickerView release];
[menu release];
But you better create a fullscreen view with a UIDatePicker and a navigation bar. For an example see UICatalog -> Pickers sample from the iPhone DevCenter.
Try adding following line to resolve disabled buttons issue
[menu sendSubviewToBack:pickerView];
Dmitry's answer is almost correct. However, the frame of the actionsheet is too small, and therefore touches near the bottom of the picker are ignored. I have corrected these problems:
UIActionSheet *menu = [[UIActionSheet alloc] initWithTitle:#"Date Picker"
delegate:self
cancelButtonTitle:#"Cancel"
destructiveButtonTitle:nil
otherButtonTitles:#"OK",nil];
// Add the picker
UIDatePicker *pickerView = [[UIDatePicker alloc] init];
pickerView.datePickerMode = UIDatePickerModeTime;
[menu addSubview:pickerView];
[menu showInView:_mainView];
CGRect menuRect = menu.frame;
CGFloat orgHeight = menuRect.size.height;
menuRect.origin.y -= 214; //height of picker
menuRect.size.height = orgHeight+214;
menu.frame = menuRect;
CGRect pickerRect = pickerView.frame;
pickerRect.origin.y = orgHeight;
pickerView.frame = pickerRect;
[pickerView release];
[menu release];
This works for me
NSString *title = UIDeviceOrientationIsLandscape([UIDevice currentDevice].orientation) ? #"\n\n\n\n\n\n\n\n\n" : #"\n\n\n\n\n\n\n\n\n\n\n\n" ;
UIActionSheet *actionSheet = [[UIActionSheet alloc]
initWithTitle:[NSString stringWithFormat:#"%#%#", title, NSLocalizedString(#"SelectADateKey", #"")]
delegate:self cancelButtonTitle:nil destructiveButtonTitle:nil otherButtonTitles:#"Ok", nil];
[actionSheet showInView:self.view];
UIDatePicker *datePicker = [[[UIDatePicker alloc] init] autorelease];
datePicker.datePickerMode = UIDatePickerModeDate;
[actionSheet addSubview:datePicker];
a little tricky but it works!
Buttons at top, picker at bottom:
UIActionSheet *menu = [[UIActionSheet alloc] initWithTitle:#"Date Picker"
delegate:self
cancelButtonTitle:#"Cancel"
destructiveButtonTitle:nil
otherButtonTitles:#"OK",nil];
// Add the picker
UIDatePicker *pickerView = [[UIDatePicker alloc] init];
pickerView.datePickerMode = UIDatePickerModeTime;
[menu addSubview:pickerView];
[menu showInView:_mainView];
CGRect menuRect = menu.frame;
menuRect.origin.y -= 214;
menuRect.size.height = 300;
menu.frame = menuRect;
CGRect pickerRect = pickerView.frame;
pickerRect.origin.y = 174;
pickerView.frame = pickerRect;
[pickerView release];
[menu release];
Make sure you show the UIActionSheet in the right view when inside a UITabBarController to avoid interactivity problems at the bottom:
[actionSheet showInView:self.parentViewController.tabBarController.view];
Possibly not directly answering the specific question (how to get the UIDatePicker to fit), but for an implementation of UIActionSheet which presents a UIDatePicker (also others) please see ActionSheetPicker. From it's Readme:
Easily present an ActionSheet with a PickerView, allowing user to select from a number of immutable options. Based on the HTML drop-down alternative found in mobilesafari.
Also:
Some code derived from marcio's post on Stack Overflow
[ Add UIPickerView & a Button in Action sheet - How? ]
Even if one doesn't use the code, it's good reading before you roll your own.
Update:
This version is deprecated: use ActionSheetPicker-3.0 instead.