Анимация похожа на открытие приложения в ios7

Я хочу создать анимацию, похожую на приложение, открытую в iPhone в iOS7. В этой анимации он просто показывает, что приложение открывается с этой точки и закрывается в той же точке.

Кто-нибудь может мне помочь?

Ответ 1

@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;
}

вы можете протестировать его, создав образец проекта следующим образом:

  • сделайте два скриншота из симулятора, как я сделал (рабочий стол и календарь), или возьмите эти два: домашний экран/calendar
  • добавить 2 изображения и 1 кнопку в раскадровку
  • сделать представление фонового изображения большим, чем весь экран
  • а другой вид изображения с этими размерами: {16,113,60,60}
  • создайте IBOutlet для обеих (самые первые две строки кода)
  • установите для цели действия кнопки значение -(void)test

storyboardanimation изображение раскадровки (слева) и переход анимации (справа)

Ответ 2

Я лично предпочитаю использовать CGAffineTransformMakeScale() и установить -[CALayer affineTransform] в этом случае.

affineTransform очень проста в использовании и имеет несколько приятных, неявных преимуществ от Core Animation. Примерами являются такие вещи, как обработка неправильного изменения начала фрейма и упрощение reset до первоначального размера, если это необходимо - вы никогда не потеряли его в первую очередь!

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

и

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

Ответ 3

Насколько я знаю, эта анимация создается с использованием скриншотов. Он обновляет фрейм представления и одновременно обеспечивает плавный переход от логотипа приложения к скриншоту из приложения. Я подражал открытию приложения iPod (музыки) с нижнего правого угла устройства до размера экрана:

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

Затем используйте строки ниже, если вы хотите анимировать размер кадра:

[UIView animateWithDuration:0.3f
                      delay:0.0f
                    options:UIViewAnimationOptionBeginFromCurrentState
                 animations:^{

    [v setFrame:frameFinal];

} completion:nil];

Изменить: не понимал, что масштабирование также включает фон. Код ниже не проверен (я не работаю), поэтому ожидайте некоторые дефекты и опечатки.

Предположим, у вас есть два слоя на представлении контроллера вида. Непосредственно на vc есть приложение, которое вы хотите открыть, и назовите его finalView. На верхнем слое есть окно со всеми приложениями, которое будет масштабироваться и исчезать в вашем приложении, что является за ним. Давайте назовем его firstView.

Исходный cond: firstView имеет фрейм 320 x 480 (это окно со всеми значками приложения). У него есть альфа 1. finalView имеет один и тот же фрейм и альфу, но он стоит за firstView. Final cond: finalView все равно будет иметь один и тот же фрейм и альфу. Но firstView будет увеличиваться в нижнем правом углу (будет иметь огромный кадр) и исчезать (альфа → 0).

//Исходный cond: (Или еще лучше использовать 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];

Затем используйте строки ниже, если вы хотите анимировать размер кадра:

[UIView animateWithDuration:0.3f
                      delay:0.0f
                    options:UIViewAnimationOptionBeginFromCurrentState
                 animations:^{

                                 [v setFrame:frameFinal];

                              } completion:nil];

Ответ 4

У меня небольшое репо, которое использует UICollectionViewFloatLayout для создания эффекта масштабирования, https://github.com/MichaelQuan/ios7ZoomEffect. Это еще работа, но основная идея есть

Код макета:

@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 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;
        }

    }
}

Чтобы развернуть ячейку с использованием этого кода макета, установите в качестве опции selectedCellFrame и selectedIndexPath ячейку, которую вы хотите развернуть, и вызовите performBatchUpdates:completion: в виде коллекции. Чтобы свернуть набор selectedCellFrame = CGRectNull и selectedIndexPath = nil и вызвать performBatchUpdates:completion: