animation similar to opening app in ios7

后端 未结 4 1116
清酒与你
清酒与你 2020-12-29 12:02

I want to create an animation similar to app opens in iPhone in iOS7. In this animation it just shows that app is opening from which point and closing at same point.

相关标签:
4条回答
  • 2020-12-29 12:09

    As far as I know, that animation is made using screenshots. It updates the frame of the view and simultaneously makes a smooth transition from the app logo to the screenshot from the app. I have imitated the opening of the iPod (music) application from the bottom right corner of the device to the screen size:

    UIView * v = [[UIView alloc]init];
    CGSize size = self.view.bounds.size;
    CGRect frameInitial = CGRectMake(size.width - 30, size.height - 30, 20, 20);
    CGRect frameFinal = CGRectMake(0,0, size.width, size.height);
    [v setFrame:frameInitial];
    

    Then use the lines below when you want to animate the frame size:

    [UIView animateWithDuration:0.3f
                          delay:0.0f
                        options:UIViewAnimationOptionBeginFromCurrentState
                     animations:^{
    
        [v setFrame:frameFinal];
    
    } completion:nil];
    

    Edit: Did not realize that the zooming also included the background. The code below is not tested (I am not at work) so expect some defects and typos.

    Imagine you have two layers on the view controller's view. Directly on the vc there is the app you want to be opened, lets call it finalView. And on the top layer there is the window with all apps, which will zoom and fade into your app, which is a view behind it. Lets call it firstView.

    Initial cond: firstView has a frame of 320 x 480 (It is a window with all the app icons). It has an alpha of 1. finalView has the same frame and alpha, but it is behind firstView. Final cond: finalView will still have the same frame and alpha. But firstView will zoom into bottom right corner (will have a huge frame) and fade out (alpha -> 0).

    //Initial cond: (Or better yet use IB)

    CGRect frameInitial = CGRectMake(0,0, self.view.size.width, self.view.size;
    CGRect frameFinal = CGRectMake(self.view.size.width * -4 ,self.view.size.height * -5, self.view.size.width * -5,self.view.size.width * -6);
    [v setFrame:frameInitial];
    

    Then use the lines below when you want to animate the frame size:

    [UIView animateWithDuration:0.3f
                          delay:0.0f
                        options:UIViewAnimationOptionBeginFromCurrentState
                     animations:^{
    
                                     [v setFrame:frameFinal];
    
                                  } completion:nil];
    
    0 讨论(0)
  • 2020-12-29 12:14
    @property (weak, nonatomic) IBOutlet UIImageView *bg;
    @property (weak, nonatomic) IBOutlet UIImageView *cal;
    …
    
    bool nowZoomed = NO;
    CGRect iconPosition = {16,113,60,60}; // customize icon position
    
    - (CGRect)zoomedRect // just a helper function, to get the new background screen size
    {
        float screenWidth = UIScreen.mainScreen.bounds.size.width;
        float screenHeight = UIScreen.mainScreen.bounds.size.height;
    
        float size = screenWidth / iconPosition.size.width;
        float x = screenWidth/2 - (CGRectGetMidX(iconPosition) * size);
        float y = screenHeight/2 - (CGRectGetMidY(iconPosition) * size);
    
        return CGRectMake(x, y, screenWidth * size, screenHeight * size);
    }
    
    - (IBAction)test
    {
        float animationDuration = 0.3f; //default
        if (nowZoomed) // zoom OUT
        {
            [UIView animateWithDuration:animationDuration animations:^{ // animate to original frame
                _cal.frame = iconPosition;
                _bg.frame = UIScreen.mainScreen.bounds;
            } completion:^(BOOL finished) {
                [UIView animateWithDuration:animationDuration/2.0f animations:^{ // then fade out
                    _cal.alpha = 0.0f;
                } completion:^(BOOL finished) {
                    _cal.hidden = YES;
                }];
            }];
        }
        else // zoom IN
        {
            _cal.alpha = 0.0f;
            _cal.hidden = NO;
            [UIView animateWithDuration:animationDuration/2.0f animations:^{ // fade in faster
                _cal.alpha = 1.0f;
            }];
            [UIView animateWithDuration:animationDuration animations:^{ // while expanding view
                _cal.frame = UIScreen.mainScreen.bounds;
                _bg.frame = [self zoomedRect];
            }];
        }
        nowZoomed = !nowZoomed;
    }
    

    you can test it, by creating a sample project like this:

    • make two screenshots from simulator like I did (homescreen and calendar view) or grab these two: homescreen / calendar
    • add 2 image views and 1 button into storyboard
    • make the background image view as big as the whole screen
    • and the other image view with this dimensions: {16,113,60,60}
    • create an IBOutlet for both (the very first two lines of code)
    • set the button action target to -(void)test

    storyboard animation the storyboard picture (left) and animation transition (right)

    0 讨论(0)
  • 2020-12-29 12:21

    I have small repo that uses a UICollectionViewFloatLayout to create the zoom effect, https://github.com/MichaelQuan/ios7ZoomEffect. It is still a work in progress but the basic idea is there

    The layout code is:

    @interface ExpandingCollectionViewLayout ()
    
    @property (nonatomic, assign) CGRect selectedCellFrame;
    @property (nonatomic, strong) NSIndexPath *selectedIndexPath;
    
    @end
    
    - (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
    {
        NSArray *layoutAttributes = [super layoutAttributesForElementsInRect:rect];
    
        [layoutAttributes enumerateObjectsUsingBlock:^(UICollectionViewLayoutAttributes *obj, NSUInteger idx, BOOL *stop) {
            [self _transformLayoutAttributes:obj];
        }];
    
        return layoutAttributes;
    }
    
    - (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath
    {
        UICollectionViewLayoutAttributes *layoutAttributes = [super layoutAttributesForItemAtIndexPath:indexPath];
    
        [self _transformLayoutAttributes:layoutAttributes];
    
        return layoutAttributes;
    }
    
    - (void)_transformLayoutAttributes:(UICollectionViewLayoutAttributes *)layoutAttributes
    {
        if (self.selectedIndexPath != nil)
        {
            if ([layoutAttributes.indexPath isEqual:self.selectedIndexPath]) {
                // set the frame to be the bounds of the collectionView to expand to the entire collectionView
                layoutAttributes.frame = self.collectionView.bounds;
            } else {
                //scale = collectionView.size / cell_selected.size
                //translate = (scale - 1)(cell_i.center - cell_selected.center) + (collectionView.center - cell_selected.center)
    
                CGRect collectionViewBounds = self.collectionView.bounds;
    
                CGRect selectedFrame = self.selectedCellFrame;
                CGRect notSelectedFrame = layoutAttributes.frame;
    
                // Calculate the scale transform based on the ratio between the selected cell's frame and the collection views bound
                // Scale on that because we want everything to look scaled by the same amount, and the scale is dependent on how much the selected cell has to expand
                CGFloat x_scale = collectionViewBounds.size.width / selectedFrame.size.width;
                CGFloat y_scale = collectionViewBounds.size.height / selectedFrame.size.height;
                CGAffineTransform scaleTransform = CGAffineTransformMakeScale(x_scale, y_scale);
    
                // Translation based on how much the selected cell has been scaled
                // translate based on the (scale - 1) and delta between the centers
                CGFloat x_zoomTranslate = (x_scale - 1) * (CGRectGetMidX(notSelectedFrame) - CGRectGetMidX(selectedFrame));
                CGFloat y_zoomTranslate = (y_scale - 1) * (CGRectGetMidY(notSelectedFrame) - CGRectGetMidY(selectedFrame));
                CGAffineTransform zoomTranslate = CGAffineTransformMakeTranslation(x_zoomTranslate, y_zoomTranslate); //Translation based on how much the cells are scaled
    
                // Translation based on where the selected cells center is
                // since we move the center of the selected cell when expanded to full screen, all other cells must move by that amount as well
                CGFloat x_offsetTranslate = CGRectGetMidX(collectionViewBounds) - CGRectGetMidX(selectedFrame);
                CGFloat y_offsetTranslate = CGRectGetMidY(collectionViewBounds) - CGRectGetMidY(selectedFrame);
                CGAffineTransform offsetTranslate = CGAffineTransformMakeTranslation(x_offsetTranslate, y_offsetTranslate);
    
                // multiply translations first
                CGAffineTransform transform = CGAffineTransformConcat(zoomTranslate, offsetTranslate);
                transform = CGAffineTransformConcat(scaleTransform, transform);
    
                layoutAttributes.transform = transform;
            }
    
        }
    }
    

    To expand a cell using this layout code, set both the selectedCellFrame and selectedIndexPath to the cell you want expanded and call performBatchUpdates:completion: on the collection view. To collapse set selectedCellFrame = CGRectNull and selectedIndexPath = nil and call performBatchUpdates:completion:

    0 讨论(0)
  • 2020-12-29 12:28

    I personally prefer to use CGAffineTransformMakeScale() and setting -[CALayer affineTransform] in this case.

    affineTransform is super easy to use and comes with a few nice, implicit benefits from Core Animation. Examples being that does things like handling of changing the frame's origin for you implicitly and making it really easy to reset back to the initial size if needed -- you never lost it in the first place!

    [UIView animateWithDuration:0.3 animations:^{
        view.layer.affineTransform = CGAffineTransformMakeScale(10.0, 10.0); // To make a view larger:
        otherView.layer.affineTransform = CGAffineTransformMakeScale(0.0, 0.0); // to make a view smaller
    }];
    

    and

    // To reset views back to their initial size after changing their sizes:
    [UIView animateWithDuration:0.3 animations:^{
        view.layer.affineTransform = CGAffineTransformIdentity;
        otherView.layer.affineTransform = CGAffineTransformIdentity;
    }];
    
    0 讨论(0)
提交回复
热议问题