MBProgressHUD with CustomView: Why can't I animate my custom view?

﹥>﹥吖頭↗ 提交于 2021-01-29 09:50:58

问题


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’s bounds, not to B’s center. 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, like frame, in the coordinate system of B. But B’s center is defined in the coordinate system of its superview, which might be completely different. Sometimes you won’t notice the difference (specifically if B’s origin 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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!