问题描述:

This related SO question does display a similar issue to my own but the answer supplied does not fix my problems.

I have a refresh button which I animate when it is tapped. It's a UIBarButtonItem, created in storyboard and the image I used to create is:

AFAIK - the image is square and the circle depicted is centred and true.

When I tap the image I call this animation code:

#define DEGREES_TO_RADIANS(angle) ((angle) / 180.0 * M_PI)

- (void)animateRefreshButton;

{

UIBarButtonItem *item = self.refreshButton;

UIView *view = [item valueForKey:@"view"];

[UIView animateWithDuration:0.5 delay:0.3 options:UIViewAnimationOptionCurveEaseInOut animations: ^

{

view.transform = CGAffineTransformMakeRotation(DEGREES_TO_RADIANS(180));

} completion: ^(BOOL finished)

{

view.transform = CGAffineTransformMakeRotation(DEGREES_TO_RADIANS(0));

}];

}

However the animation "jumps" and it also affects the title. See gif:

I have tried quite a few things but the video above is about the best animation I can get to. Things I've tried include:

  • adding the image to the buttons's custom view and animating that.
  • adjusting image insets (but it's different on every device and rotation)
  • adjusting the size of the image itself to match the size

    the navigation bar "turns it into", approx 50x30

  • applying different animation blocks to try and mask the "jump" (horrible)

If anyone had a similar problem and solved it then any pointers would be great

Also, if I'm mis-guided with the technique I'm using please let me know.

I did check the image and it seems fine but someone out there may know better.

网友答案:

Ok - the secret to this was discovering that by default the image that is used by a UIBarButtonItem is re-sized to 50x30

UIBarButtonItem *item = self.refreshButton;
UIView *view = [item valueForKey:@"view"];

At this point I put a breakpoint in and checked the frame of the view and it was size 50 x 30 !

In addition I added a custom view of the rotation image, sized 50 x 30 to the button and rotated that.

#pragma mark - UIRefreshControl method(s)

- (void)configureSpinningView;
{
    // 50x30 is the size that the nav bar sets for the buttons image...

    self.refreshControlSpinningImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 50, 30)];
    self.refreshControlSpinningImageView.image = [UIImage imageNamed:@"btnSync"];
    self.refreshControlSpinningImageView.autoresizingMask = UIViewAutoresizingNone;
    self.refreshControlSpinningImageView.contentMode = UIViewContentModeCenter;

    UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(refreshTapped:)];

    [self.refreshControlSpinningImageView addGestureRecognizer:tapRecognizer];
}

#pragma mark - aimation(s)

#define DEGREES_TO_RADIANS(angle) ((angle) / 180.0 * M_PI)
- (void)animateRefreshButton;
{
    [self.refreshButton setCustomView:self.refreshControlSpinningImageView];

    [UIView animateWithDuration:0.5 delay:0.3 
options:UIViewAnimationOptionCurveEaseInOut animations: ^
    {
        self.refreshControlSpinningImageView.transform = CGAffineTransformMakeRotation(DEGREES_TO_RADIANS(180));
    } completion: ^(BOOL finished)
    {
        self.refreshControlSpinningImageView.transform = CGAffineTransformMakeRotation(DEGREES_TO_RADIANS(0));

        [self.refreshButton setCustomView:nil];
      }];
} 

#pragma mark - IBAction(s)

- (IBAction)refreshTapped:(UIBarButtonItem *)sender;
{
  //deletia

  [self animateRefreshButton];
}

Here is the video of the fix:

相关阅读:
Top