问题
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
centerto 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
centeris defined, likeframe, in the coordinate system of B. But B’scenteris defined in the coordinate system of its superview, which might be completely different. Sometimes you won’t notice the difference (specifically if B’soriginis{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
NSNumberliterals, 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