Whatever Im trying to my view controller won't appear offscreen (as it I want to, because I have a handler(menu) that will make the animation from offscreen to onscreen. After realising (from other posts) that I can't change a views frame before it appears, makes sense to use this approach:
-(void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
//self.view.frame = CGRectInset(self.view.frame, 100, 50);
self.view.frame = CGRectMake(50, 50, 50, 50);
}
But still, it is presented exactly on screen as any standard view controller would (0,0,width, height)
How to solve?
You have the method willLayoutSubviews: or viewDidLayoutSubviews
Called to notify the view controller that its view is about to layout
its subviews.When a view's bounds change, the view adjusts the position of its subviews.
So instead of doing it in view will appear,over ride the willLayoutSubviews:
-(void)viewWillLayoutSubviews{
[super viewWillLayoutSubviews];
[self.view setFrame:CGRectMake(100, 100, 100, 100)];
}
Have you considered adding all of your views to another view, functioning as a container view, and then adding that one view to your view controller's view? Then you'd be able to position that container view freely before it appears.
You could access the ViewControllers view property and set it in the loadView() and it will only be set once and therefore not messing up any custom animations.
The view controller calls this method when its view property is requested but is currently nil. This method loads or creates a view and assigns it to the view property.
Because viewWillLayoutSubviews() would be setting the frame every time subviews are laid out.
override func loadView() {
super.loadView()
self.view.frame = CGRect(x: self.view.bounds.origin.x,
y: self.view.bounds.origin.y,
width: self.view.bounds.width,
height: self.view.bounds.height * 0.8
}
Related
I'm having trouble programmatically moving a button.
I am using this code in viewDidLoad and I am NOT using auto-layout:
button.frame.origin = CGPoint(x: 0, y: 0)
But the button remains in its original position on the screen at runtime.
The strange thing is, the coordinates are actually being updated, but not being represented on the screen.
If I run the following code:
print(button.frame.origin.x) // prints 45.0
button.frame.origin = CGPoint(x: 0, y: 0)
print(button.frame.origin.x) // prints 0.0
But on screen the button remains at 45.
What am I doing wrong?
Change your button position in viewDidAppear method and it will change it's position at run time and your code will be:
override func viewDidAppear(animated: Bool) {
button.frame.origin = CGPoint(x: 0, y: 0)
}
From this post: Difference between viewDidLoad and viewDidAppear
viewDidLoad is called exactly once, when the view controller is first loaded into memory. This is where you want to instantiate any instance variables and build any views that live for the entire lifecycle of this view controller. However, the view is usually not yet visible at this point.
viewDidAppear is called when the view is actually visible, and can be called multiple times during the lifecycle of a View Controller (for instance, when a Modal View Controller is dismissed and the view becomes visible again). This is where you want to perform any layout actions or do any drawing in the UI - for example, presenting a modal view controller.
Perhaps a long shot (?), but...
Instead of:
button.frame.origin = CGPoint(x: 0, y: 0)
Try:
var frame = button.frame
frame.origin = CGPoint(x: 0, y: 0)
button.frame = frame
EDIT: The reason I suggest this is, I think button.frame returns a copy of the button's frame rect, so you are not directly changing the origin sub-property of the original CGRect instance, and that is why the change is not reflected.
Well, I guess that UIView subclasses listen on -setFrame: setter only (when talking around -frame property); changing the its sub-value, which is even non-object (and thus cannot overload setters on -size and -origin attributes to react), won't have any immediate effect IMO.
In that case, you have to modify the frame via another variable and set it back via -setFrame: as other posts suggest.
I would like to display a small UIView with some text in the center of a UITableViewController when I call the showHud method.
- (void) showHud {
UIView *paintView=[[UIView alloc]initWithFrame:CGRectMake(150, 150, 120, 30)];
[paintView setBackgroundColor:[UIColor yellowColor]];
[self.view addSubview:paintView];
}
Actually the problem with this code is that the view doesn't stays on its place, when I scroll the tableview it goes up with cells. Is it possible to pin it somehow?
I don't think you can achieve that with a UITableViewController because the view property of such controller is a UITableView, so the content will always scroll with it.
You need to create a regular UIViewController and add a UITableView to that controller's main view. Then anything else you add to that main view, will stay in place as it is outside of the table view.
Try implementing scrollViewDidScroll delegate method and change the frame of paintView according to tableview offset.
eg:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
CGPoint offset = scrollView.contentOffset
[paintView setFrame:CGRectMake(150, 150+offset.y, 120, 30)];
}
But the best way would be to create a simple UIViewController.
You must use UItableViewController because of pullToRefresh controller?
UI could add a view to the window and position it to the very front:
UIView testView = [[UIIView alloc]initWithFrame:CGRectMake(10, [[UIScreen mainScreen]applicationFrame].size.height - 85 , 75, 75)]; [[[[[NSApplication sharedApplication] mainWindow] contentView] addSubview:testbox]; addSubview: testView]; testView.layer.zPosition = MAXFLOAT;
An UITableViewController is typically embedded in a "parent" view controller, like UINavigationController. Its UITableView will then have a superview, like UINavigationControllerWrapperView. Even if your table view controller is a root view controller, the table view's superview is UIWindow.
So you can safely assume that your table view always has a superview. Then add your UIView to this superview instead of the table itself:
//Note: frame should be different here as it's in the superview's coordinate system
UIView *paintView=[[UIView alloc]initWithFrame:CGRectMake(150, 150, 120, 30)];
[paintView setBackgroundColor:[UIColor yellowColor]];
[self.view.superview addSubview:paintView];
I have a view controller where the views are laid out manually (no xib). This is done in viewDidLayoutSubviews. I want to animate one of the views, but the animation doesn't work (no observable motion of the view) because viewDidLayoutSubviews appears to be called immediately as the animation begins.
Relevant portions of code:
- (void)viewDidLayoutSubviews
{
[super viewDidLayoutSubviews];
logo.frame = CGRectMake(0, 0, 640, 360);
}
- (void)shrink
{
[UIView animateWithDuration:0.5 animations:^{logo.frame = CGRectMake(0, 0, 320, 180);}];
}
The shrink method is called when another timer fires, so it's not called straight away on view controller creation.
If I set up logo.frame elsewhere and remove that line from viewDidLayoutSubviews, then the animation works correctly.
What is the explanation for this behaviour, and what is a recommended way to work around it?
Have you tried to call animation method in viewDidApper ? Instead of use viewDidLayoutSubviews try to use viewDidLoad
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 modal view controller that I show with UIModalPresentationPageSheet. The problem is that its default size is too large for my content: so I want to resize its frame to adjust accordingly with my content.
Does anyone know of a way/trick to do this?
Thanks.
Actually you can resize the view controller that gets presented with UIModalPresentationPageSheet. To do it you need to create a custom view controller class and add the following to the class:
<!--The header file-->
#interface MyViewController: ViewController{
//Used to store the bounds of the viewController
CGRect realBounds;
}
<!--In the .m file-->
//viewDidLoad gets called before viewWillAppear, so we make our changes here
-(void)viewDidLoad{
//Here you can modify the new frame as you like. Multiply the
//values or add/subtract to change the size of the viewController.
CGRect newFrame = CGRectMake(self.view.frame.origin.x,
self.view.frame.origin.y,
self.view.frame.size.width,
self.view.frame.size.height);
[self.view setFrame:newFrame];
//Now the bounds have changed so we save them to be used later on
_realBounds = self.view.bounds;
[super viewDidLoad];
}
//viewWillAppear gets called after viewDidLoad so we use the changes
//implemented above here
-(void)viewWillAppear:(BOOL)animated{
//UIModalpresentationPageSheet is the superview and we change
//its bounds here to match the UIViewController view's bounds.
[super viewWillAppear:animated];
self.view.superview.bounds = realBounds;
}
And then you display this view controller with a UIModalPresentationPageSheet. And that's it. This does work for iOS 5.1.1 and iOS 6 as of the date of this post.
You can't resize a UIModalPresentationPageSheet because its size is not modifable.
This works for resizing a view controller that's presented as UIModalPresentationFormSheet. I would give this a try, I'm not sure if it'll work or not:
navController.modalPresentationStyle = UIModalPresentationFormSheet;
[self presentModalViewController:navController animated:YES];
//these two lines are if you want to make your view smaller than the standard modal view controller size
navController.view.superview.frame = CGRectMake(0, 0, 200, 200);
navController.view.superview.center = self.view.center;