Я хочу создать анимацию, похожую на приложение, открытую в iPhone в iOS7. В этой анимации он просто показывает, что приложение открывается с этой точки и закрывается в той же точке.
Кто-нибудь может мне помочь?
Я хочу создать анимацию, похожую на приложение, открытую в iPhone в iOS7. В этой анимации он просто показывает, что приложение открывается с этой точки и закрывается в той же точке.
Кто-нибудь может мне помочь?
@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;
}
{16,113,60,60}
IBOutlet
для обеих (самые первые две строки кода)-(void)test
изображение раскадровки (слева) и переход анимации (справа)
Я лично предпочитаю использовать 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;
}];
Насколько я знаю, эта анимация создается с использованием скриншотов. Он обновляет фрейм представления и одновременно обеспечивает плавный переход от логотипа приложения к скриншоту из приложения. Я подражал открытию приложения 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];
У меня небольшое репо, которое использует 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: