MBProgressHUD с CustomView: почему я не могу анимировать свой пользовательский вид? - PullRequest
0 голосов
/ 06 января 2020

Это как-то не работает ... почему? Как я могу получить вращающийся нестандартный пропеллер без анимации?

-(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];
}

Но мой пропеллер остается стати c ...

1 Ответ

0 голосов
/ 04 апреля 2020

Если пропеллер не вращается, это может произойти, если вы сразу не добавили это view в иерархию вида. Как правило, целесообразно добавить представление в иерархию представлений до вас 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;
}

Выход:

enter image description here


Некоторые несвязанные наблюдения:

  • Если вы хотите центрировать вид A в середине вида B, установите для вида A center координаты к средней точке B bounds, а не B center. Например, вы никогда не хотите делать:

    A.center = B.center;
    

    То, что вы хотите, это:

    A.center = CGPointMake(B.bounds.origin.x + B.bounds.size.width / 2, B.bounds.origin.y + B.bounds.size.height / 2);
    

    Я знаю, похоже, что это должно быть то же самое, но это не так. center определяется, как frame, в системе координат B. Но B center определяется в системе координат его суперпредставления, , которое может быть совершенно другим. Иногда вы не заметите разницу (в частности, если B origin равен {0, 0}), но это предполагает неправильное понимание различных систем координат, а если B не равно {0, 0}, то все будет неправильно.

  • Вы можете использовать NSNumber литералы, заменив [NSNumber numberWithFloat:0.0f] на @(0).

  • Вам действительно не нужен этот вид контейнера, поэтому вы можете упростить процедуру, как показано ниже.

    - (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;
    }
    
...