I have taken UIView as subview in View Controller
#property(nonatomic,retain) IBOutlet UIView *subview;
then I am adding custom UIView class in subview like this ,
- (void)showdetail
{
CGRect frameToset = CGRectMake(0, 0, self.subview.frame.size.width,self.subview.frame.size.height) ;
customUIViewPaging *demoView = [[customUIViewPaging alloc] initWithFrame:frameToset];
... // so on
[self.subview addSubview:demoView];
}
In portrait mode it works perfectly but in landscape I am updating the frame like this,
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
[self showdetail];
}
then after it works perfectly in landscape and portrait then I am pushing a another view from this view and landscaping Pushed view after back coming in this view then frame size not getting perfectly (Subview frame not updating the frames while orientation when coming back from another view)
I have tried to put needsUpdateConstraints but it seems not working
[self.subview needsUpdateConstraints];
Check this example
I am not going to Autolayout direction as you want correct frame when view appears ... If you want correct width than call it -(void)viewDidLayoutSubviews{..}
-(void)viewDidLayoutSubviews{
NSLog(#"%f",self.subview.frame.size.width); //here you get correct width
}
now the other problem is you are adding subviews everytime when screen rotates or this method calls .. so better to prevent that by removing previous view...
Related
Im trying to draw/place a view (which contains a picker view and a toolbar offscreen). On launch the View is still on the screen despite changing its coordinates in viewDidLoad.
self.pickerViewContainer.frame = CGRectMake(0, 722, 320, 207);
Im using the storyboard. I have created the view in the storyboard, visible in the view controller. I thought i could redraw it off screen as per coordinates above.
When you use Auto layout write your view's frame related code in viewDidLayoutSubviews
Here is a solution
-(void) viewDidLayoutSubviews
{
self.pickerViewContainer.frame = CGRectMake(0, 722, 320, 207);
}
I have a custom UIViewController which create a view containing an action bar at the top (view with 4 buttons), a tableview and then another view below the tableview. Layout is done all in code and is not using auto layout.
Everything works perfectly on various device with iOS 7.0 and 7.0.2, but in the simulator, the root view of the controller get anchored at the top right corner of the screen (0,0) instead of below the navigation bar.
I'm going to force the relay out in the viewDidAppear: method, but this seem like a hack...
Thanks for any insights
Edit: added an image. You can see the UIView highlighted. As ManicMonkOnMac mentioned, the UIView is under the toolbar (but this only happens in the simulator, on the device, the view lines up fine)
In the loadView method on the controller, i set the frame when creating the view:
- (void)loadView
{
// Our parent view controller will resize us appropriately. The size set
// here is a convenience for initial view layout.
self.view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 320)];
self.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
}
But this frame is later changed. Not by my code, though, but by UIkit code)
Edit2: addded loadView method body
EDIT: After going through session 201 of WWDC 2013, I think I have the solution.
in iOS 7 there is a property that you can set on your view controllers to specify whether you want the views to be overlapped by navigation bar.
viewController.edgesForExtendedLayout = UIRectEdgeNone;//UIRectEdgeAll specifies that nav bars should overlap the view.
Unlike iOS 6, navigation bars are placed over the views in iOS 7.
Use the frame size that excludes the navigation bar.
code:
CGRect frame = CGRectMake(self.view.frame.origin.x,self.view.frame.origin.y+self.navigationController.navigationBar.frame.size.height,self.view.frame.size.width,self.view.frame.size.height);
CustomView *view = [[CustomView alloc] initWithFrame:frame];
[self.view addSubview: view];
I've UIViewController and another UIView with some images and labels on it.
I wanna change orientation and it works well, I can change aqGridview frame when rotating device,
My code :
- (void)makePortraitOrientation {
[gridView setFrame:CGRectMake(0, 43, 768,961)]; //works like a charm
HeaderView* dsd = [[HeaderView alloc] initWithParentID:self]; // in this way there is no errors but nothing changes
[dsd.label setFrame:CGRectMake(0, 0, 0, 0)];
[dsd setNeedsDisplay];
[self.HeaderView.label setFrame:CGRectMake(0, 0, 0, 0)]; //error, no object HeaderView in UIViewController
[self.HeaderView.label CGRectMake]
}
Header file of UIView
#interface HeaderView : UIView{
id parentID;
UIButton *menu;
UIImageView *icon;
NSString *product;
THLabel *label;
NSMutableArray *backs;
}
The main problem is how can i change frames and places of images and
labels which is on another UIView, not in my UIViewController ?
All the views created programatically.
Based on your controls frame you need to adjust the position of our controls while rotating the device.
Access controls which is in our view controller like this. [self.button setFrame:];
Access the sub view controls frame like this: [self.subviewname.control setFrame:];
Based on the orientation you need to handle the frames. You can use auto re-sizing also.
Update:
Make sure whether your sub view is added properly in your view controller like this :
[self.view addSubView:self.mysubView];
Increase the score of your sub view(HeaderView) as well.
I just want (for now) to get the dimensions of a subview on the view controller's instantiation.
[This is a reduction to as simple a case I can find of a previous question. I am trying to figure out why subViews of scenes in Storyboards are not behaving the way I expect, which is to say: like XIBs do - I just want to get dimensions of my subviews before anything is actually drawn to the screen]
To condense the problem down to a new, clean project, I do this:
create a new, single view project with "using Storyboard" checked
add a single UIView to the default existing MainStoryboard_iPad.storyboard (and change its background to green to make it more easily seen - beyond shrinking the dimensions some, this is the only change I make from the default UIView I drag onto the scene)
option-click the ViewController.h file in the navigator to bring it up in its own frame underneath the Storyboard frame and insert a pair of braces underneath the #interface directive
control-click-and-drag from the UIView in the Storyboard to ViewController.h and tell it to name the outlet firstViewFirstSubView
So we now have for ViewController.h:
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController
{
IBOutlet UIView *firstViewFirstSubView;
}
#end
Then, I add this method to the ViewController.m:
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
NSLog(#"View Controller will appear. firstViewFirstSubView: %# ", firstViewFirstSubView);
NSLog(#"subView's dimmensions: %f by %f at %f, %f", firstViewFirstSubView.frame.size.width,
firstViewFirstSubView.frame.size.height,
firstViewFirstSubView.frame.origin.x,
firstViewFirstSubView.frame.origin.y);
}
At this point, I expect to be able to get the dimensions of the UIView subview. I get all 0s, though:
2012-11-15 15:21:00.743 StoryboardViewBounds[11132:c07] View Controller will appear. firstViewFirstSubView: <UIView: 0x9379730; frame = (0 0; 0 0); autoresize = TM+BM; layer = <CALayer: 0x9378e40>>
2012-11-15 15:21:00.744 StoryboardViewBounds[11132:c07] subView's dimmensions: 0.000000 by 0.000000 at 0.000000, 0.000000
What am I doing wrong? It seems like this should be very straightforward, so I think I must be missing something simple, whether throwing the right switch in the Storyboard editor or implementing a method that Storyboard needs.
Those dimensions are calculated and set when the call to layoutSubviews is made, which occurs after viewWillAppear. After layoutSubviews is called on the UIVIew you can get the dimensions.
Look at implementing this method in your view controller: viewDidLayoutSubviews. At this point you should be able to get dimensions of your subviews. Note that this call is available starting in iOS 5.0 but since you reference storyboards I assume you are working at or above that anyway.
- (void)viewDidLayoutSubviews
{
[super viewDidLayoutSubviews];
NSLog(#"View Controller did layout subviews. firstViewFirstSubView: %# ", firstViewFirstSubView);
NSLog(#"subView's dimmensions: %f by %f at %f, %f", firstViewFirstSubView.frame.size.width,
firstViewFirstSubView.frame.size.height,
firstViewFirstSubView.frame.origin.x,
firstViewFirstSubView.frame.origin.y);
}
There is a Related issue that I am compelled to address, which hopefully will save someone else a day of debugging:
I am finding out that in Storyboard:
segue-push does not cause subViews to be laid out at -viewDidLayoutSubviews (they are instead laid out at some other time just before -viewDidAppear).
Whereas...
segue-modal and [navController.storyboard presentViewController:] does cause subViews to be laid out at -viewDidLayoutSubviews.
The solution is to put [self.mySubView layoutSubviews] within the viewController's -viewDidLayoutSubviews method in order to manually load the subViews within mySubView.
My case was that I had a custom gradient button that was not properly initializing it's visual appearance.
The button was contained within a scrollView that contained a CustomView which contained the custom gradient button.
So, basically... a button within a view within a scrollView.
The app starts out with a UINavigationController having some other ViewController1 loaded.
ViewController1 contains a button which, when pressed, launches a storyboard segue-push to ViewController2.
(this was arranged in storyboard by control-dragging from the button in ViewController1 to ViewController2).
ViewController2 contains the scrollview/customView/customButton.
In ViewController2's -viewDidLayoutSubviews, I initialize the customButton which is a custom Gradient Button having it's own .h/.m files.
GradientButton.m has an initLayers method which configures it graphically and requires the bounds/frame property of the button to be initialized.
However...
in ViewController2's -viewDidLayoutSubviews, self.customButton had a frame of 0,0,0,0.
A few notes:
Yes, I am calling [super viewDidLayoutSubviews] at the beginning of -viewDidLayoutSubviews.
The only view that has been laid out at -viewDidLayoutSubviews is self.view (ViewController2's initial view, as connected in Storyboard's connections panel. in my case - self.view is a scrollView).
To resolve:
in ViewController2, I created an outlet self.bottomView for the view that contained self.customButton.
in ViewController2's -viewDidLayoutSubviews, I call [self.bottomView layoutSubviews]
This will then cause customButton's frame/bounds to be properly set.
Next, I call [self.customButton initLayers] which now properly initializes my custom gradient button.
A few notes about ViewController2's -viewDidLayoutSubviews: calling [self.view layoutSubviews] causes bottomView's frame to be initialized, but NOT customButton's frame.
In terms of a view hierarchy, -layoutSubviews applies only to the subViews of self.view and not to any subViews of those subViews.
This only appears to be the case with storyboard segue-push.
The storyboard segue-modal and the programmatic [navController presentViewController] both seem to correctly initialize all levels of the view hierarchy (all "subViews of subViews") by the time -viewDidLayoutSubviews is called.
I have created a subview which is used as a HUD in an iOS app. The app supports portrait and landscape display orientations.
The subview appears in portrait mode sometimes even if the mode is landscape. The subview is added by these lines:
self.infoHUDViewController = [[[InfoHUDViewController alloc] initWithNibName:#"InfoHUD" bundle:nil] autorelease];
[self.view addSubview:self.infoHUDViewController.view];
So it works very well if the subview is added in the viewDidLoad method. However, it does not work in landscape mode if the view is added in an IBAction method which responds to a button press. The subview appears as if in portrait mode (it appears 90° rotated, fills only the half screen width, and extends beyond the screen bounds).
What is really odd: In the init method of the subview's view controller the display orientation is correctly set to landscape. Am I missing something here?
I found a fix for this problem.
I added
if (UIInterfaceOrientationIsLandscape(self.interfaceOrientation)) {
self.view.frame = CGRectMake(0.0f, 0.0f, 480.0f, 320.0f);
} else {
self.view.frame = CGRectMake(0.0f, 0.0f, 320.0f, 480.0f);
}
to the viewDidLoad method. Now everything works as excepted in all situations.