可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
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. I can animate the origin of the frame, i.e. to get it slide in from wherever, but the width/height doesn't seem to animate. Code as follows:
[UIView beginAnimations:@"animateAddContentView" context:nil];
[UIView setAnimationDuration:0.4];
customView.frame= CGRectMake(self.view.frame.origin.x +5, self.view.frame.origin.y +5, 0, 150);
[self.view addSubview:customView];
customView.frame= CGRectMake(self.view.frame.origin.x +5, self.view.frame.origin.y +5, 310, 150);
[UIView commitAnimations];
I have also tried putting only the setFrame part in the animation like this:
customView.frame= CGRectMake(self.view.frame.origin.x +5, self.view.frame.origin.y +5, 0, 150);
[self.view addSubview:customView];
[UIView beginAnimations:@"animateAddContentView" context:nil];
[UIView setAnimationDuration:0.4];
customView.frame= CGRectMake(self.view.frame.origin.x +5, self.view.frame.origin.y +5, 310, 150);
[UIView commitAnimations];
But it still doesn't work!
EDIT:
As per the suggestions, I have moved it to a block based animation solution, and this is the exact code:
NSLog(@"yourview : %@",customView);
customView.frame= CGRectMake(self.view.frame.origin.x +5, self.view.frame.origin.y +5, 0, 150);
NSLog(@"yourview : %@",customView);
[self.view addSubview:customView];
NSLog(@"yourview : %@",customView);
// [customView setFrame:CGRectMake( 0.0f, 480.0f, customView.frame.size.width, customView.frame.size.height)];
[UIView animateWithDuration:0.4
delay:0
options:UIViewAnimationCurveEaseInOut
animations:^ {
NSLog(@"yourview : %@",customView);
customView.frame = CGRectMake(self.view.frame.origin.x +5, self.view.frame.origin.y +5, 310, 150);
NSLog(@"yourview : %@",customView);
}completion:^(BOOL finished) {
}];
Which still doesn't work for some reason. Possible problems I see are:
- I am loading this customView from a
nib
that is specifically 310 by 150, perhaps that is causing a problem.
- I am not importing the correct frameworks, but since I can animate the frame.origin parts of this view, I am not sure that is the case...I have
QuartzCore
and Core Graphics
all imported and stuff.
At each point in the log it is giving the correct stuff: for example, before the target frame the size is 0, 150, and after I set the frame its 310, 150. But the animation doesn't work!
回答1:
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.
回答2:
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!" );
}];
回答3:
Try this:
customView.frame= CGRectMake(self.view.frame.origin.x +5,self.view.frame.origin.y+5,0, 150);
[self.view addSubview:customView];
CGRect frame = customView.frame;
frame.size.width = 310;
[UIView animateWithDuration:0.4
animations:^{
customView.frame= frame;
}];
Or if you want to use beginAnimation method instead of block Methos , Use this :
UIView *customView=[[UIView alloc]initWithFrame:CGRectMake(self.view.frame.origin.x +5,self.view.frame.origin.y+5,0, 150)];
[self.view addSubview:customView];
CGRect frame = customView.frame;
frame.size.width = 310;
[UIView beginAnimations:@"animateAddContentView" context:nil];
[UIView setAnimationDuration:0.4];
customView.frame= frame;
[UIView commitAnimations];
回答4:
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!
回答5:
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) {
}];
回答6:
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.
回答7:
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
}