I am segueing to a view controller called SmallerVC. I want to set the size of SmallerVC to 300 X 300. So far I am not having much luck. I have tried the answers at the following link separately and then together, they don't work: ios5 - size of modal view controller with storyboard. I am using Xcode-5 and iOS-7. Has anyone successfully done this? I came to iOS with the prejudice that anything I can do on Android I should be able to do more easily on iOS. And so far iOS has been constantly disabusing me of that notion. Can such a simple thing be really so difficult?
To get to the button of things, I set my content view's color to clearColor. And sure enough, during transition it is clear, but upon transitioning a black background shows up that covers the whole screen. So my guess is I need to access and manipulate some sort of parent. Any ideas how I might do this?
UPDATE: my code
Here is the latest iteration of my code. The modal segue is set in storyboard.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"smaller_view_id"]) {
if ([segue.destinationViewController isKindOfClass:[SmallerVC class]]) {
UIViewController *container = (SmallerVC *)segue.destinationViewController;
container.modalPresentationStyle = UIModalPresentationFormSheet;
id sourceController = segue.sourceViewController;
UIView *destinationView = [container view];
CGFloat x, y, w, h;
x = 10;//destinationView.superview.frame.origin.x;
y = 50;//destinationView.superview.frame.origin.y;
w = 300; // Your desired modal view width
h = 300; // Your desired modal view height
destinationView.superview.frame = CGRectMake(x, y, w, h);
destinationView.frame = CGRectMake(x, y, w, h);
destinationView.superview.center = [[sourceController view] center];
[container setModalPresentationStyle:UIModalPresentationFormSheet];
[container setModalTransitionStyle:UIModalTransitionStyleCrossDissolve];
// [sourceController presentViewController:container animated:YES completion:nil];
NSLog(#"SEGUE CALL IS SEEN");
#pragma warning - pass in previous review data
}
}
}
Related
I'm trying to create a UIScrollView with 3 UIViewController subviews. I'm done some research and it seems that the answer to this question provides a good solution Setting up UIScrollView to swipe between 3 view controllers, but I'm not sure. I downloaded the sample code which the answerer nicely posted https://github.com/gneil90/CustomContainerViewController and my question is as follows:
BViewController *bViewController = [[BViewController alloc]init];
[self addChildViewController:bViewController];
[self.scrollView addSubview:bViewController.view];
[bViewController didMoveToParentViewController:self];
CViewController *cViewController = [[CViewController alloc]init];
CGRect frame = cViewController.view.frame;
frame.origin.x = 320;
cViewController.view.frame = frame;
[self addChildViewController:cViewController];
[self.scrollView addSubview:cViewController.view];
[cViewController didMoveToParentViewController:self];
self.scrollView.contentSize = CGSizeMake(640, self.view.frame.size.height);
self.scrollView.pagingEnabled = YES;
The code in the sample project initializes both UIViewControllers at once. Is there any way to lazy load them/would this provide any kind of performance enhancements? If 2 of my viewcontrollers download data, I wouldn't want to download this data unless the user was actually viewing these screens, but with this kind of initialization it would seems as though the user quickly viewed both of them.
You can use UIScrollView delegate method, initialize only first view controller as you are doing.
For rest of your view controller you can create property. In UIScrollView delegate method scrollViewDidScroll do following-
// Check at what index, to second VC or third VC
if (some condition, you can define this based on scroll postion) {
// Check if second view controller
if (!self.cViewController) {
cViewController = [[CViewController alloc]init];
CGRect frame = cViewController.view.frame;
frame.origin.x = 320;
cViewController.view.frame = frame;
}
// similarly for third
}
Using this view controller are initialized as they are needed.
My universal app uses NIBs for its settings screens. I'd like to use the same NIBs for both iPhone and iPad.
Thus on iPad, I use a UIPopoverController in the MainViewController and for settings, simply display the iPhone-sized NIBs, to show what is called the SettingsViewController. The popover is sized 320x460 points.
This causes a problem, because the iPhone version draws a number of things above the status bar programmatically, and for the iPad version this is not necessary. Current situation on iPad:
As you can see, there's a big empty space above the "Settings" title. Thus what I want, is to shift the view controller up about 20 points, inside the popover:
The popover is instantiated as follows in the MainViewController:
settingsPopoverController = [[UIPopoverController alloc] initWithContentViewController:popoverNavigationController];
settingsPopoverController.popoverContentSize = CGSizeMake(320, 460);
settingsPopoverController.delegate = self;
popoverNavigationController.navigationBarHidden = YES;
In the SettingsViewController, I set the frame as follows:
- (void)viewDidLoad
{
self.contentSizeForViewInPopover = CGSizeMake(320, 460);
}
And later in the SettingsViewController, I try to create an offset as follows:
- (void)viewWillLayoutSubviews
{
// shift it up
CGRect frame = self.view.frame;
frame.origin.y = -20;
[self.view setFrame:frame];
}
This does not shift the content up a bit. How to go about?
To clarify: I want to move down the "viewport" that the popover shows.
Try to:
myPopover.autoresizingMask=UIViewAutoresizingNone;
Or:
myPopover.autoresizingMask=UIViewAutoresizingFlexibleHeight || UIViewAutoresizingFlexibleWidth;
You can also try to put your code in -(void)viewDidLayoutSubviews method.
If this answers did not help, try set popoverLayoutMargins (property) instead of setFrame: for example:
popover.popoverLayoutMargins=UIEdgeInsetsMake (
CGFloat 50, //top
CGFloat 50,//left
CGFloat 50,//bottom
CGFloat 50//right
);
I am adding a UIViewController subView to another UIViewController.
It works great. But I am having a hard time trying to center the subview in the middle of the parent view.
I read up and I found 2 lines of code that worked for other people but its not working for me.
Could anyone point out my problem??
those are:
popupController.view.center = [self.view convertPoint:self.view.center fromView:self.view.superview];
and
popupController.view.center = CGPointMake(self.view.bounds.size.width / 2, self.view.bounds.size.height / 2);
Parent View Controller code:
- (IBAction)selectRoutine:(id)sender {
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Storyboard" bundle:nil];
createRoutinePopupViewController* popupController = [storyboard instantiateViewControllerWithIdentifier:#"createRoutinePopupView"];
// popupController.view.center = [self.view convertPoint:self.view.center fromView:self.view.superview];
popupController.view.center = CGPointMake(self.view.bounds.size.width / 2, self.view.bounds.size.height / 2);
//Tell the operating system the CreateRoutine view controller
//is becoming a child:
[self addChildViewController:popupController];
//add the target frame to self's view:
[self.view addSubview:popupController.view];
//Tell the operating system the view controller has moved:
[popupController didMoveToParentViewController:self];
}
child settings
Seems like you reposition your view controllers view after centering it. Probably in didMoveToParentViewController:.
Move the centering code to the end of selectRoutine: method
- (IBAction)selectRoutine:(id)sender
{
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Storyboard" bundle:nil];
createRoutinePopupViewController* popupController = [storyboard instantiateViewControllerWithIdentifier:#"createRoutinePopupView"];
[self addChildViewController:popupController];
[self.view addSubview:popupController.view];
[popupController didMoveToParentViewController:self];
//do the centering here
popupController.view.center = [self.view convertPoint:self.view.center fromView:self.view.superview];
}
Or better yet, move it to the didMoveToParentViewController:
- (void)didMoveToParentViewController:(UIViewController *)parent
{
//whatever code you have here
self.view.center = self.view.superview.center;
}
Possibly you will have to modify this code a bit. But i'm certain that your problem is incorrect (execution-time-wise) placement of the centering code - that gets subsequently overriden by some other view-positioning.
For moving a subview to the center of view i tried this
YourView.center = CGPointMake(self.view.center.x,self.view.center.y);
The solutions posted here works for me. In general if you want the spinner to come between the UIAlertController message (which generally is at the center of the UIAlertController) and any action buttons below (like Ok or cancel), slightly adjust it's height like
spinnerIndicator.center = CGPointMake(self.superview.view.bounds.width / 2,
(self.alertVC.view.bounds.height / 2) * 1.07)
// The superview of the spinnerIndictator here is the UIAlertController.
The ratio 1.07 positions the spinner just between the message and action buttons beneath for all available iPhone screens based on my experimentation.
I am writing an iPad app that needs to know the usable area of the view for drawing purposes. The view is added into a Navigation controller, so I have the status bar plus the navigation controller both taking up a certain number of pixels. My app happens to be in landscape mode, although I don't think that's relevant.
I am able to get the correct view size AFTER rotation using didRotateFromInterfaceOrientation. But I can't figure out how to do it without the screen being rotated.
- (void) didRotateFromInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
[self.view setFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
NSLog(#"drfi %d %d", (int)self.view.frame.size.width, (int)self.view.frame.size.height);
}
^^ that works after rotation. Not before. Can't figure out how to get accurate numbers. And I REALLY don't want to hard wire this.
I will also need this function to be device independent -- it should work on the NEW iPad as well as the older iPad resolutions. I can handle the scaling issues once I know the exact usable area. Why is this so hard? Help!!
I don't think you need to specify your frame's view within the didRotateFromInterfaceOrientation what i will suggest instead is setting some properties to your view autoresizing mask so that it automatically resize itself according to your view orientation.
By setting this for example to your view when your view is loaded (viewDidLoad method):
self.view.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
you specify that your view will change its width and height automatically and can get the right values you need to get from there.
You should read this: http://developer.apple.com/library/ios/#documentation/WindowsViews/Conceptual/ViewPG_iPhoneOS/CreatingViews/CreatingViews.html#//apple_ref/doc/uid/TP40009503-CH5-SW1
for a better understanding of views in iOS
EDIT
Also you probably want to spot what is the orientation of your device which can be accomplish with [[UIApplication sharedApplication] statusBarOrientation];
Your application looks like: there is a start up view, then in this view you will load and add a main view into window, right? Then you should do as below in your main view:
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
CGRect frame = self.view.frame;
frame.origin.y = frame.origin.y + 20.0;
self.view.frame = frame;
}
return self;
}
Try this.
CGRect frame = [UIScreen mainScreen].bounds;
CGRect navFrame = [[self.navigationController navigationBar] frame];
/* navFrame.origin.y is the status bar's height and navFrame.size.height is navigation bar's height.
So you can get usable view frame like this */
frame.size.height -= navFrame.origin.y + navFrame.size.height;
You can get this dynamically by combining an instance method with a category method:
Instance method:
This assumes that your view controller (self) is embedded within a navigation controller.
-(int)getUsableFrameHeight {
// get the current frame height not including the navigationBar or statusBar
return [MenuViewController screenHeight] - [self.navigationController navigationBar].frame.size.height;
}
Class category method:
+(CGFloat)screenHeight {
CGFloat screenHeight;
// it is important to do this after presentModalViewController:animated:
if ([[UIApplication sharedApplication] statusBarOrientation] == UIDeviceOrientationPortrait ||
[[UIApplication sharedApplication] statusBarOrientation] == UIDeviceOrientationPortraitUpsideDown){
screenHeight = [UIScreen mainScreen].applicationFrame.size.height;
} else {
screenHeight = [UIScreen mainScreen].applicationFrame.size.width;
}
return screenHeight;
}
The above will consistently give you the usable frame height after the status bar and navigation bar have been removed, in both portrait and landscape.
Note: the class method will automatically deduct the 20 pt for the status bar - then we just subtract the navigation header variable height (32 pt for landscape, 44 pt for portrait).
We have a UISplitViewController and under condition X, we need to display a UIPopover from one of the UIBarButtonItem of the Master view.
Supposedly, in order to have the frame/layout correct, we do this code from the Master view controller's viewDidLoad event. Somehow the first time the UISplitViewController is shown, the frame of the Master is 1024x724 whereas we'd expect it to be 320x724. As a result, the call to [UIPopover presentFromBarButtonItem:] uses a wrong referential and since it's a right BarButtonItem, the popover appears all the way to the right of the screen (at about x = 980px)
If we delay the displaying by a split second (via a Timer/delay, sooo dirty) then it's all fine.
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
CGRect masterViewFrame = self.view.frame;
NSLog(#"Master View Frame: %#", NSStringFromCGRect(masterViewFrame));
if (someCondition) {
[self showPopover:self.theBarButton];
}
}
The NSLog here shows 1024x724 # 0x0
Thoughts?
You can do something like this:
//Check if you really are in a UISplitViewController
CGRect frame = self.view.frame; //this is the default value
if(self.splitViewController)
{
//you are trying to access the frame of this VC's view via the splitViewController
//this should return the correct size
frame = [[[self.splitViewController.viewControllers objectAtIndex:0] view] frame];
}