I have this subview I want to add to my main view, but make it expand from the origin. I read some of the Apple documentation but I don\'t understand where I am making mistake.
Here is a fun way of animating your views. In my example I have a touch action that will execute the block animations and a BOOL to make sure to reset the views back to their original states.
First you put 2 UIViews on a UIViewController (you can color them different colors for contrast). Connect them to your "MainViewController.h" file you create to control the big view. The .h file should look like this:
#import <UIKit/UIKit.h>
@interface MainViewController : UIViewController
@property (weak, nonatomic) IBOutlet UIView *topView;
@property (weak, nonatomic) IBOutlet UIView *bottomView;
@end
and your .m file should look like this:
#import "MainViewController.h"
#define kViewAnimateWithDuration 0.35f
#define kViewDelay 0.05f
@interface MainViewController ()
@property (nonatomic) BOOL setTouch;
@end
@implementation MainViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
self.setTouch = NO;
}
return self;
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
UITouch *touch = [touches anyObject];
CGPoint touchLocation = [touch locationInView:self.view];
float width_tp = self.topView.frame.size.width;
float height_tp = self.topView.frame.size.height;
float width_b = self.bottomView.frame.size.width;
float height_b = self.bottomView.frame.size.height;
if ((CGRectContainsPoint(self.bottomView.frame, touchLocation)) && !self.setTouch){
[UIView animateWithDuration:kViewAnimateWithDuration
delay:kViewDelay
options:UIViewAnimationOptionCurveEaseInOut | UIViewAnimationOptionAllowUserInteraction
animations:^{
//Move frame or transform view
[self.topView setFrame:CGRectMake(self.topView.frame.origin.x, self.topView.frame.origin.y, width_tp, height_tp + 171)];
[self.bottomView setFrame:CGRectMake(self.bottomView.frame.origin.x, self.bottomView.frame.origin.y +171, width_b, height_b -171)];
} completion:^(BOOL finished) {
self.setTouch = YES;
}];
}
if ((CGRectContainsPoint(self.bottomView.frame, touchLocation)) && self.setTouch) {
[UIView animateWithDuration:kViewAnimateWithDuration
delay:kViewDelay
options:UIViewAnimationOptionCurveEaseInOut | UIViewAnimationOptionAllowUserInteraction
animations:^{
//Move frame or transform view
[self.topView setFrame:CGRectMake(self.topView.frame.origin.x, self.topView.frame.origin.y, width_tp, height_tp - 171)];
[self.bottomView setFrame:CGRectMake(self.bottomView.frame.origin.x, self.bottomView.frame.origin.y -171, width_b, height_b +171)];
} completion:^(BOOL finished) {
self.setTouch = NO;
}];
}
}
So just make sure the topView has some small dimensions like x:0,y:0 width:320 height:43 and bottomView like x:0 y:40 width:320 height:528. Remember to color the backgrounds different colors. Then just run the program and you should see animations.
For me I think one of the more important lines in the code is setFrame: that to me enables the frame to automagically redisplays the rectangle without having to use the DrawRect method. Setting the property changes the point specified by the center property and the size in the bounds rectangle accordingly.
Of course there are other fun ways to do this but I hope this can help someone make iOS look magical like it is supposed to be! Happy journeys!
To make a view "grow" into place, don't animate the frame. Animate the transform.
Load your subview from the nib. Set its transform to a scale of 0:
view.transform = CGAffineTransformMakeScale(0,0);
Then add it to your superview.
Inside the animation block, set the transform to identity:
view.transform = CGAffineTransformIdentity;
And the view will grow to normal size. You may need to fiddle with the anchor point to make it grow from the right point.
You can also change the frame within the block, but to move a view only I prefer to change the center property, you shouldn't try to set the frame if you also have a transform.
For bonus points, you can also animate to a slightly bigger than 1.0 scale, then animate back to the identity transform in a chained animation from the completion block. This makes the view "pop" out of the screen like an alert view.
Try using a block it will be more clear.
// First create the view if you haven't already
UIView *myView = [[UIView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 100.0f, 100.0f)];
// Add it as a subview.
[myViewController.view addSubview:myView];
CGRect newFrameOfMyView = CGRectMake(0.0f, 0.0f, 200.0f, 200.0f);
/*
* Alternatively you could just set the width/height or whatever you'd like with this:
* CGRect newFrameOfMyView = myView.frame;
* newFrameOfMyView.size.height = 200.0f;
* newFrameOfMyView.size.width = 200.0f;
*/
[UIView animateWithDuration:0.3f
animations:^{
myView.frame = newFrameOfMyView;
}
completion:^(BOOL finished){
NSLog( @"woo! Finished animating the frame of myView!" );
}];
If your viewcontrollers viewWillLayoutSubviews (or such) sets the "initial" frame of yourView, then that apparently gets called during the animation cycle, and would therefore reset the frame set by the animation.
Swift 4
UIView.animate(withDuration: 0.3, animations: {
self.whiteBackgroundView.transform = CGAffineTransform(scaleX: 0.1, y: 0.1)
self.view.layoutIfNeeded()
}) { (finished) in
// end of animation
}
Important points
1) Add view to your parentView before animation, with starting frame.
2) Then just give target frame inside animation block
You no longer need this since you are adding view from nib..
//UIVIew yourView = [[UIView alloc] initWithFrame:YOUR_STARTING_FRAME];
//[self.view addSubview:yourView];
.........
.........
.........
just give the animation code on your view.. Make sure yourView is not nil (Seems to me that is the case..)
NSLog(@"yourview : %@",yourView);
[UIView animateWithDuration:your_duration
delay:your_starting_delay
options:UIViewAnimationCurveEaseInOut
animations:^ {
yourView.frame = YOUR_TARGET_FRAME;
}completion:^(BOOL finished) {
}];