Animating only the image in UIBarButtonItem

2019-02-10 16:27发布

Ive seen this effect in 2 apps and I REALLY want to find how to do it.

The animation is in a UIBarButtonItem, and is only to the image. The image is a + symbol, and it rotates to a X.

If you want to see the effect you have to start a conversation with someone and next to the text input theres the + button for images and emoji's. Or heres a video of the effect in another app, after he taps the bar button you see it rotate to a X, http://www.youtube.com/watch?v=S8JW7euuNMo.

I have found out how to do the effect but only on a UIImageView, I have to turn off all the autoresizing and the view mode has to be centered, then apply the rotation transform to it. I have tried many ways of trying to have it work in a bar item and so far the best way is adding a image view instance, then setting it up and setting the view mode centered and autoresizing off and then using that image view for a custom bar item view. But when i do this, the effect works except while its doing it, the image will go off to the side a little bit instead of staying where it already is. Ive tried getting the center before the animation and set it during the animation but that doesnt do anything.

3条回答
贪生不怕死
2楼-- · 2019-02-10 17:06

Recently had to do the same thing in Swift. I created a tutorial that includes starter and final projects, and goes step-by-step with some tips sprinkled in. The code looks like this:

@IBOutlet weak var rightBarButton: UIBarButtonItem! {
    didSet {
        let icon = UIImage(named: "star")
        let iconSize = CGRect(origin: CGPointZero, size: icon!.size)
        let iconButton = UIButton(frame: iconSize)
        iconButton.setBackgroundImage(icon, forState: .Normal)
        rightBarButton.customView = iconButton
        rightBarButton.customView!.transform = CGAffineTransformMakeScale(0, 0)

        UIView.animateWithDuration(1.0,
            delay: 0.5,
            usingSpringWithDamping: 0.5,
            initialSpringVelocity: 10,
            options: .CurveLinear,
            animations: {
                self.rightBarButton.customView!.transform = CGAffineTransformIdentity
            },
            completion: nil
        )    

        iconButton.addTarget(self, action: "tappedRightButton", forControlEvents: .TouchUpInside)        
    }
}

func tappedRightButton(){
    rightBarButton.customView!.transform = CGAffineTransformMakeRotation(CGFloat(M_PI * 6/5))
    UIView.animateWithDuration(1.0) {
        self.rightBarButton.customView!.transform = CGAffineTransformIdentity
    }
}
查看更多
虎瘦雄心在
3楼-- · 2019-02-10 17:17

So the answer for this is you have to make a instance of the Image view, then set it up with no resizing and view mode is centered. Then add the image view to a UIButton with custom type, and then use the button as the custom view for the bar item.

- (IBAction)animate {
    [UIView animateWithDuration:0.5 delay:0.0 options:UIViewAnimationOptionCurveLinear animations:^{
        imageView.transform = CGAffineTransformMakeRotation(DEGREES_TO_RADIANS(45));
    } completion:^(BOOL finished) {
        imageView.transform = CGAffineTransformMakeRotation(DEGREES_TO_RADIANS(0));
        if ([imageView.image isEqual:[UIImage imageNamed:@"Add.png"]]) {
            imageView.image = [UIImage imageNamed:@"Close.png"];
        }
        else imageView.image = [UIImage imageNamed:@"Add.png"];
    }];
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"Add.png"]];
    imageView.autoresizingMask = UIViewAutoresizingNone;
    imageView.contentMode = UIViewContentModeCenter;
    UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
    button.frame = CGRectMake(0, 0, 40, 40);
    [button addSubview:imageView];
    [button addTarget:self action:@selector(animate) forControlEvents:UIControlEventTouchUpInside];
    imageView.center = button.center;
    barItem = [[UIBarButtonItem alloc] initWithCustomView:button];
    navItem.rightBarButtonItem = barItem;
}
查看更多
贪生不怕死
4楼-- · 2019-02-10 17:20

I wanted to keep the expanded tapping size that the native UIBarButtonItem view provides (such as -initWithBarButtonSystemItem:target:action: versus -initWithCustomView:).

Here's a basic implementation of my code.

- (void)setup {
    self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(navigationBarRightAction)];
}

- (void)navigationBarRightAction {
    UIView *itemView = [self.navigationItem.rightBarButtonItem performSelector:@selector(view)];
    UIImageView *imageView = [itemView.subviews firstObject];

    if (self.shouldRotate) {
        imageView.contentMode = UIViewContentModeCenter;
        imageView.autoresizingMask = UIViewAutoresizingNone;
        imageView.clipsToBounds = NO;
        imageView.transform = CGAffineTransformMakeRotation(M_PI_4);

    } else {
        imageView.transform = CGAffineTransformIdentity;
    }
}
查看更多
登录 后发表回答