I have created a UIView in a storyboard. See here for more information. My issue is when the user "logs in" then I present a new view bringing it from the left side of a screen and the main view slides off to the left, like a push navigation, but all programmatically.
So I have decided to animate this "navigation" using the following code.
view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 480)];
view.backgroundColor = [UIColor whiteColor];
//add stuff to view
[view addSubview: label];
view.frame = CGRectMake(320, 0, 0, 480);
view.clipsToBounds = YES;
[self.view addSubview:view];
//show view
[UIView animateWithDuration:.5
animations:^{
self.view.frame = CGRectMake(0,0,0,480); //move self.view off left
view.frame = CGRectMake(0, 0, 320, 480); //move new view in place
}];
My view is being successfully displayed but the existing view, self.view is not going off the left side of the screen like I want it. It moves, but it doesn't take it's components with it... When I comment out //view.frame - CGRectMake(0,0,320,480); inside the animation, so I don't display the new view I get this in the simulator on login.
The white background of the view leaves the screen but the components do not. This causes an issue because when I put the two together it does not look like the "new view" is replacing the old view like a navigation push controller but instead sliding over it. Is there a way to move these components with the self.view when I move it off the screen
Thanks for the help!
I am not sure if you can move self.view. Even if it is possible, it's not a good idea...
Anyway your code
self.view.frame = CGRectMake(0,0,0,480);
doesn't slide the view. It scales the view into a zero-width rectangle, which explain why its subviews are still there. By default subviews are aligned to top-left corner of their superviews, and since self.view's top-left hasn't moved (still (0, 0)), they remain the same. The proper way to slide a view off the screen is:
self.view.frame = CGRectMake(-320,0,320,480); // width & height MUST remain unchanged
Still, this will NOT work, since you have made view a subview of self.view... which means this line:
view.frame = CGRectMake(0, 0, 320, 480);
will set view.frame relative to self.view which now has been slided off the screen! So they will be both gone. Another good reason why you shouldn't play with self.view.frame.
IMHO, you should create a view v1 as the main view, and v2 the view that appears when logged in. Make them both subviews of self.view, hide v2 behind v1 and when user logs in, slide v1 off the screen as described above. Or maybe put v1 to the right of v2, and slide them both (so v1 will be sliding out why v2 sliding in, similar to a navigation controller).
Related
I have a storyboard with a square imageView in the middle at: 280,140 (vertical)
When the application starts i am able to move this imageView by pressing buttons. I move the imageView using:
_mainImage.frame = CGRectMake(_mainImage.frame.origin.x + 2, _mainImage.frame.origin.y, _mainImage.frame.size.width, _mainImage.frame.size.height);
while the application is running i keep adding new imageViews to the mainView:
UIImageView *imgView;
imgView = [[UIImageView alloc] initWithFrame:CGRectMake(0, yCoordinate, 50, 10)];
imgView.backgroundColor = [UIColor whiteColor];
[self.view addSubview:imgView];
each time i call this code the square imageView i have placed in the middle and moved around, gets set back to its starting position. It seems like the mainView gets "reset" each time the addSubview gets called. Is there any way i can add a subview without having the mainView "reset"?
Most likely your view is set up using Autolayout (this is the default for storyboards or nibs) and when you add a new subview, a layout pass is performed which resets your views position back to that defined by its original constraints.
You should move your view by updating its constraints, or turn off Autolayout. There are lots of posts around explaining how to do either of these things.
UINavigationBars within a UINavigationController. . . they don't participate in frame animations. Useful, but exactly not what I want right now. Is there a way to turn this off?
I know I could set the showsNagitationBar property to hidden, and add my own to the view, put am looking at possible alterntives.
What I'm Trying to Achieve:
I've put my UINavigationController into a (screen-sized) container view, and want to slide it across to reveal a side menu. . last time that I did this I had custom push/pop methods on the RootVC, and my own navigation bar - worked fine, though a fair amount of boiler-plate code to set up.
This time I've got the same kind of requirement - main content is push/pop based, and some auxiliary VCs that can be revealed from the side. And so for another approach, and considering that this app's look and feel is very standard, I just included a UINavigationController within the RootVC and expected it to work the same.
However the UINavigationBar stays anchored in place, while the rest of the content within the container view moves.
I am not entirely sure what you are trying to achieve, but when using a navigation controller, the entirety of what you see on screen (your top view controller's view PLUS your navigation bar) is rooted in the Navigation Controller's view.
This means that if you do something like:
[UIView animateWithDuration:1.0 animations:^{
CGRect frame = self.navigationController.view.frame;
frame.size.width -= 30;
self.navigationController.view.frame = frame;
}];
You will get your view AND the navigation bar to shrink.
EDIT: You can add/remove the sliding-in views to the navigation controller's view where it is appropriate (for example the nav controller is your root view controller, you could do it in your appdelegate's didFinishLaunch: method). The following code would show an entirely red view sliding in from the left. In your case, this view would be the one from your side view controller.
UIView *left = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
left.backgroundColor = [UIColor redColor];
CGRect ff = left.frame;
ff.origin.x = -ff.size.width;
left.frame = ff;
[self.navigationController.view addSubview:left];
[UIView animateWithDuration:1.0 animations:^{
CGRect frame = self.navigationController.view.frame;
frame.origin.x += 50;
self.navigationController.view.frame = frame;
}];
Is something like this what you were looking for?
I noticed that with a NavigationController on an iPhone, the height is 460. So it includes the whole screen except the status bar.
However, when I add something at coordinate 0, it shows up after the NavigationBar, although the size of the navigation bar is included in the height (meaning the entire frame of this view sticks off the screen).
Did I make a mistake? If not, why is it structured this way?
NSLog(#"Frame: %#", [NSValue valueWithCGRect: self.view.frame]); // prints {(0, 20), (320, 460)}
UIScrollView* scrollView = [[UIScrollView alloc] initWithFrame: CGRectMake(0, self.navigationController.navigationBar.frame.size.height, self.view.frame.width, 50)];
[self.view addSubview: scrollView]; // showing up 44px *after* the nav bar
I already answered your other similar question, but here is one for this.
In viewDidLoad you will see the views height as 460 because at that point it hasn't resized to account for the Nav Bar.
But If you printed the same frame out in say viewWillAppear you will see that now the frames height has adjusted for the Nav Bar.
So if you want to add something in viewDidLoad, you need to add it based on the views frame, add whichever resizing mask will do the job you want, and see it adjust correctly once the view appears.
I have a UIView configured through Storyboard. This view (self.view) has one child, a button (self.cartButton). Later in the code I add a subview to this view:
[self.view addSubview:self.cart.view];
I have the following method:
- (void)openCart
{
[UIView animateWithDuration:2 animations:^{
self.cartButton.frame = CGRectMake(0.0f, 0.0f, self.cartButton.frame.size.width, self.cartButton.frame.size.height);
self.cart.view.frame = CGRectMake(0.0f, 0.0f, self.cart.view.frame.size.width, self.cart.view.frame.size.height);
}];
}
I think it should move both objects to the top of the screen, but what really happens is that the cartButton animates to the bottom most position, and the cart view to the top. Why does this happen? Did I mess up the coordinate systems somewhere?
UPDATE: If I comment out the second line in the animation (animating the cart view), cartButton flies to the top.
UPDATE2: It has something to do with my cartView. It is a generic view (created in Storyboard). When I try to do the same animation for example with a NavigationController, it works.
UPDATE3: If my cart view has no subviews, it works fine. If it has anything in it (a button, navigationBar, anything...), it does not work.
I want to change the existing view in a UIViewController to a new view. The new view contains the old view and a little banner view.
Doing this fairly simple change leaves me with a black view.
My code looks like this
UIView *existingView = self.view;
UIView *newView = [[UIView alloc] initWithFrame:existingView.frame];
UIView *bannerView = [[UIView alloc] initWithFrame:CGRectMake(0, (self.view.frame.size.height - 50), 320, 50)];
CGRect existingViewFrame = existingView.frame;
existingViewFrame.size.height -= 50;
existingView.frame = existingViewFrame;
[newView addSubview:existingView];
[newView addSubview:bannerView];
self.view = newView;
However when switch Tabs and come back to the view which changed the view is shown just like I want. I guess I need to set a flag or something to tell the controller to redraw it's (new) view.
Edit
I wrote an simple example for this problem. You can find it on GitHub: https://github.com/Oemera/ChangeView
You did not say where you do this. It may be that you need to save the original view's super view, then add the new view to that views subViews array. I'm betting that is the problem.