How do I change the size of a view programmatically in iOS.
I am developing an iOS app in Objective C.
I have a couple of views which are hidden and shown according to a certain logic using the following method:
-(void)hideGroupStats{
[groupTimeToFinishForeText setHidden:YES];
[lblTimeToFinish setHidden:YES];
[groupTimeToFinishBG setHidden:YES];
}
below them in my view hierarchy there is a view holding a map with "scale to fit mode".
however, when the other views are hidden it doesnt resize to take the space.
i am new to ios development so i could be missing somting very simple.
As per the Apple documentation for UIView (see extract below) when calling setHidden:YES this doesn't actually remove the view from it's superview it just makes it disappear so it is equivalently still there you just can't see it. There are a couple of ways to hide the view so you get the affect that you are after but the main one I'd go with is altering the UIViews frame (like David Ansermots as says given +1)
mapView.frame = CGRectMake(newX, newY, newWidth, newHeight);
with newX, newY, newWidth and newHeight all being variables that you set somewhere to determine the size and location of the UIView. However I'd stick this line within some sort of animation to give the user a better user experience so I'd personally do something like :
- (void)showView:(UIView *)view withAnimationForFrame:(CGRect)frame
{
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.5];
[UIView setAnimationCurve:UIViewAnimationCurveEaseIn];
view.frame = CGRectMake(frame);
[UIView commitAnimations];
}
- (void)hideView:(UIView *)view withAnimationForFrame:(CGRect)frame
{
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.5];
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
view.frame = CGRectMake(frame);
[UIView commitAnimations];
}
Changing the frame size and/or location should make the other views that you want to scale do it automatically like you want.
Extract from Apple Documentation for UIView
Setting the value of this property to YES hides the receiver and setting it to NO shows the receiver. The default value is NO.
A hidden view disappears from its window and does not receive input events. It remains in its superview’s list of subviews, however, and participates in autoresizing as usual. Hiding a view with subviews has the effect of hiding those subviews and any view descendants they might have. This effect is implicit and does not alter the hidden state of the receiver’s descendants.
Hiding the view that is the window’s current first responder causes the view’s next valid key view to become the new first responder.
The value of this property reflects the state of the receiver only and does not account for the state of the receiver’s ancestors in the view hierarchy. Thus this property can be NO but the receiver may still be hidden if an ancestor is hidden.
You have to add code to resize your view like :
mapView.frame = CGRectMake(newX, newY, newWidth, newHeight);
you can directly set the frame of your view like:-
[yourViewObject SetFrame :CGRectMake(newX, newY, newWidth, newHeight)];
And if you want to set the frame of your view on dependent any other view(map view) then you can simply use :-
yourviewObj.frame = mapview.frame
Hope this will be helpful for you
Related
I am trying to make a UITableView appear when a user taps on a button and disappear when the button is re-tapped.
I implemented the following code but nothing seems to appear when I tap the button.
- (IBAction)dropDown:(UIButton *)sender
{
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.6];
CGAffineTransform transfrom = CGAffineTransformMakeTranslation(0, 200);
self.markersTableView.transform = transfrom;
self.markersTableView.alpha = self.markersTableView.alpha * (-1) + 1;
[UIView commitAnimations];
}
What may potentially be the issue?
EDIT:
I was able to make the UITableView appear and disappear by adding self.markersTableView.hidden = YES; in viewDidLoad() and self.markersTableView.hidden = NO; in the IBAction method.
However, the table view disappears when I initially tap on the button as shown in the screenshot:
The fading of the rows is an indication it is moving down the screen, and then it disappears.
It only reappears when I re-tap on the UIButton the 2nd time.
Any clues?
Don't use a transform on your table view. That will make it LOOK like it's in a different position, but it won't respond to taps correctly.
Instead, use the newer UIView block-based animation methods and change the view's center.
The code might look like this (if you're NOT using auto-layout)
[UIView AnimateWithDuration: .2
animations: ^
{
CGPoint center = self.markersTableView.center;
center.y += 200;
self.markersTableView.center = center;
}
];
If you're using auto-layout, though, that won't work and you will need to animate the view's position using constraints.
From memory, here's an outline of how to do auto-layout based animations: You would create a vertical position constraint on your table view and connect the constraint to an IBOutlet in your view controller. In your animation code you change the constant of the constraint (the vertical position) and then in the animation block, send the view a needsLayout message.
I have two UIImageView's, one that is a background that should scroll, and one an avatar that should move positions based on user input.
I'm able to move the avatar with no problem, and I'm able to scroll my background when necessary with:
CGRect oldPos = _fieldView.frame;
CGRect newPos = CGRectMake(oldPos.origin.x, oldPos.origin.y - 400, oldPos.size.width, oldPos.size.height);
[UIView animateWithDuration:5.0
delay:0.0
options: UIViewAnimationCurveEaseOut
animations:^{
[_fieldView setFrame:newPos];
}
completion:^(BOOL finished){
NSLog(#"Done with animation");
}];
However, when this _fieldview scrolls, my avatar on top of it scrolls with it. How can I move my background image without affecting the other images?
A few other settings that may affect this:
I've disabled AutoLayout
My background image mode is set to AspectFill
I'm using a storyboard with a single UIView
Thank you for any suggestions.
EDIT
The avatar, runnerView, is added as a subview of _fieldView, with
[_fieldView addSubview:_runnerView];
You want your background scroll image to not be a superview to your avatar, but sibling view instead.
(Not the best representation, not sure how to make it look better though)
-Main View
--Scroll view
--Avatar
i.e.
[self.view addSubview:backgroundView];
[self.view addSubview:avatarView];
not
-Main View
--Scroll view
---Avatar
i.e.
[backgroundView addSubview:avatarView];
[self.view addSubview:backgroundView];
If it is required to be a subview, then you will have to move the avatar view an equal and opposite amount so it will stay in the same relative location.
I need to change the width of a subview depending on, say, available disk space. So I have a selector that's called upon the view controller's viewWillLayoutSubviews as such:
CGRect rect = self.usageView.bounds;
rect.size.width = self.someCalculatedwidth;
[self.usageView setFrame:rect];
[self.usageView setNeedsDisplay];
Really, I just want to change the width of the subview. It works if the view controller is the initial controller; however, if it is transitioned from, say, a Push Segue it stopped working. What happens is I'd see my desired width rendered for moment but then it gets changed to the original width as per its blueprint on the Storyboard.
The behavior feels like the iOS caches the original (storyboard) view in a block during the push segue animation, and upon completion it executes the block which doesn't have my calculations above; thereby overridden the desired view. Any idea?
There are two approaches.
The first approach is to circumvent the problem, with a side benefit of cool animation. Since I have no clue when or how many times or exactly how iOS enforces the auto-constraints, I simply delay my UIView modifications and smooth it out with animation. So I wrap view animation around the code in my selector:
[UIView animateWithDuration:.25 animations:^{
CGRect rect = self.usageView.bounds;
rect.size.width = self.someCalculatedwidth;
[self.usageView setFrame:rect];
[self.usageView setNeedsDisplay];
}];
Then I'd call my selector in my controller's viewDidAppear:animated:
[self performSelector:#selector(resetUsageView) withObject:self afterDelay:0.0];
Now most would say this is a cop-out or a kludge. And that's fair.
In the second approach I attack the root of the problem - auto layout/constraints. I add a Width constraint to my usageView in the storyboard, and connect its IBOutlet to my code.
#property (weak, nonatomic) IBOutlet NSLayoutConstraint *usageViewWidthConstraint;
Then I modify the constraint as per the calculated width in my controller's viewWillAppear:animated:
[self.usageViewWidthConstraint setConstant:self.someCalculatedWidth];
Voila! A one liner.
Now what if I want animation given I got a taste of it from the first approach? Well, constraint changes are outside the realm of animation so basically I'd need a combination of the first and second approaches. I change the UIView's frame for animation, and modify the constraint as well to "set the record straight":
[UIView animateWithDuration:.25 animations:^{
CGRect rect = self.usageView.bounds;
rect.size.width = self.someCalculatedwidth;
[self.usageView setFrame:rect];
[self.usageViewWidthConstraint setConstant:self.someCalculatedWidth]; // <<<<
[self.usageView setNeedsDisplay];
}];
I want to make a UIView animate when it's being closed. I tried reading the following:
http://felipe.sabino.me/ios/2012/05/10/ios-uiview-transition-effects/
iPhone UIView Animation Best Practice
iOS UIView Animation CATransform3DMakeRotation confusion
However, I'd like to make it transition from the side of the screen, as per the image in the Google Chrome app.
Is there another animation that is set for this? I was not able to find it... I'm assuming it has to do with animateWithDuration or a CATransform...can somebody point me in the right direction for this?
[EDIT]
I used the below post for an answer as well as this post:
Setting a rotation transformation to a UIView or its layer doesn't seem to work?
I was able to add multiple animations as per below:
[UIView animateWithDuration: .2
delay: 0
options: (UIViewAnimationOptionCurveLinear | UIViewAnimationOptionAllowUserInteraction)
animations:^{self.view.center = CGPointMake(self.view.frame.origin.x * 3, self.view.frame.origin.y * 2), self.view.transform = CGAffineTransformMakeRotation(M_PI_4/2);}
completion:nil];
Previously I was not aware you can add multiple animations so easily. That adds rotation as well as the linear movement together.
Animate your view so it moves offscreen/shrinks/expands/fades, then do the actual removal when the animation ends.
You can do this by altering the properties of the view (position/size/offset) between a beginAnimations/commitAnimations block. UIKit will then animate these properties over the time specified.
E.g something like;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.30f];
view.transform =
CGAffineTransformMakeTranslation(
view.frame.origin.x,
480.0f + (view.frame.size.height/2) // move the whole view offscreen
);
background.alpha = 0; // also fade to transparent
[UIView commitAnimations];
In the animation end notification you can then remove the view.
I've never run Chrome on iOS, so I have to try to guess what your screenshot is showing.
Does the animation go off the screen while shrinking and turning to one side?
And do you mean you want to animate a UIViewController, or a UIView? Are you closing a view controller?
If it's a view controller, how are you managing your view controllers? Are you using a navigation controller, or are you presenting a set of modal view controllers, or some other method?
I'm trying to slide my main view controller view to the right when the user taps a button. I use this code:
[UIView animateWithDuration:1
delay:0
options:UIViewAnimationOptionBeginFromCurrentState
animations:^(void){ self.view.left = 300; }
completion:nil];
The result is that view.frame.origin.x does not take into account device orientation. If the screen is landscape left, then setting x = 300 does not move the view to the right, it moves it down. I could do a big switch statement to change the relevant parameter depending on orientation but I feel like I've done this before without having to resort to such shenanigans. Am I missing something obvious?
I've tried with no options, no difference.
I'm using a category on UIView so that I don't have to type out the entire CGRectMake explicitly. The results are the same if I do it with the full CGRectMake statement.
I had the same issue. Animating the view's bounds instead of the view's frame (I am assuming this is what the category is doing) worked for me.