问题
This somehow doesn't work...why? How can I achieve a spinning custom propeller without making a gif out of the animation?
-(UIView *)propTest
{
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 37, 37)];
UIImageView *movablePropeller = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 37 , 37)];
movablePropeller.image = [UIImage imageNamed:@"MovablePropeller"];
[view addSubview:movablePropeller];
movablePropeller.center = view.center;
CABasicAnimation *rotation;
rotation = [CABasicAnimation animationWithKeyPath:@"transform.rotation"];
rotation.fromValue = [NSNumber numberWithFloat:0.0f];
rotation.toValue = [NSNumber numberWithFloat:(2 * M_PI)];
rotation.cumulative = true;
rotation.duration = 1.2f; // Speed
rotation.repeatCount = INFINITY; // Repeat forever. Can be a finite number.
[movablePropeller.layer addAnimation:rotation forKey:@"Spin"];
return view;
}
-(void)presentMyHud
{
MBProgressHUD *hud = [[MBProgressHUD alloc] initWithView:self.view];
[self.view addSubview:hud];
hud.mode = MBProgressHUDModeCustomView;
hud.customView = [self propTest];
hud.detailsLabelText = @"Getting data";
[hud show:YES];
}
But my propeller stays static...
回答1:
If the propeller is not spinning, that can happen if you didn’t immediately add this view
to the view hierarchy. Generally, it’s prudent to add the view to the view hierarchy before you addAnimation
.
- (UIView *)addPropellerToView:(UIView *)view {
UIView *containerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 37, 37)];
// make sure to add it to the view hierarchy
[view addSubview:containerView];
// if you want to center it, set its `center` to be in the middle of the `bounds` ... don't use `center`
containerView.center = CGPointMake(view.bounds.origin.x + view.bounds.size.width / 2, view.bounds.origin.y + view.bounds.size.height / 2);
// I'd just use the `bounds` of the container view; reducing the risk that we get its coordinates wrong
UIImageView *movablePropeller = [[UIImageView alloc] initWithFrame:containerView.bounds];
movablePropeller.image = [UIImage imageNamed:@"MovablePropeller"];
movablePropeller.contentMode = UIViewContentModeScaleAspectFill;
[containerView addSubview:movablePropeller];
// never set the center of a view to the center of its super view ... those are two different coordinate systems.
// in this case, this line isn't needed at all, so I'll remove it.
//
// movablePropeller.center = containerView.center;
CABasicAnimation *rotation;
rotation = [CABasicAnimation animationWithKeyPath:@"transform.rotation"];
rotation.fromValue = @(0);
rotation.toValue = @(2 * M_PI);
rotation.cumulative = true;
rotation.duration = 1.2f;
rotation.repeatCount = INFINITY;
[movablePropeller.layer addAnimation:rotation forKey:@"Spin"];
return containerView;
}
Yielding:
Some unrelated observations:
If you want to center view A in the middle of view B, set view A’s
center
to coordinates to the midpoint of B’sbounds
, not to B’scenter
. E.g., you never want to do:A.center = B.center;
What you want is:
A.center = CGPointMake(B.bounds.origin.x + B.bounds.size.width / 2, B.bounds.origin.y + B.bounds.size.height / 2);
I know it looks like it should be the same thing, but it’s not. A’s
center
is defined, likeframe
, in the coordinate system of B. But B’scenter
is defined in the coordinate system of its superview, which might be completely different. Sometimes you won’t notice the difference (specifically if B’sorigin
is{0, 0}
), but it suggests a misunderstanding of the different coordinate systems, and if B isn’t at{0, 0}
, then everything will be wrong.You can use
NSNumber
literals, replacing[NSNumber numberWithFloat:0.0f]
with@(0)
.You really don’t need that container view, so you could simplify the routine, like below.
- (UIView *)addPropellerTo:(UIView *)view { UIImageView *movablePropeller = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 37, 37)]; movablePropeller.image = [UIImage imageNamed:@"MovablePropeller"]; movablePropeller.contentMode = UIViewContentModeScaleAspectFill; [view addSubview:movablePropeller]; movablePropeller.center = CGPointMake(view.bounds.origin.x + view.bounds.size.width / 2, view.bounds.origin.y + view.bounds.size.height / 2); CABasicAnimation *rotation; rotation = [CABasicAnimation animationWithKeyPath:@"transform.rotation"]; rotation.fromValue = @(0); rotation.toValue = @(2 * M_PI); rotation.cumulative = true; rotation.duration = 1.2f; rotation.repeatCount = INFINITY; [movablePropeller.layer addAnimation:rotation forKey:@"Spin"]; return movablePropeller; }
来源:https://stackoverflow.com/questions/59611223/mbprogresshud-with-customview-why-cant-i-animate-my-custom-view