豌豆莢一覽的轉(zhuǎn)場動畫非常炫,尤其是點擊一個新聞條目跳轉(zhuǎn)到新聞正文的時候
于是我做了個類似的,放在了GitHub上
介紹一下主要實現(xiàn):
從VC1(ViewController1)跳轉(zhuǎn)到VC2的時候,主要是調(diào)用下面這個方法,這個方法有兩個參數(shù),一個是要顯示的下一個ViewController,還有一個是,動畫從那個方塊開始(因為豌豆莢一覽是從某個cell開始的動畫)
- (void) animToNextViewController:(UIViewController*)viewController beginRect:(CGRect)beginFrame {
UIWindow *window = [UIApplication sharedApplication].keyWindow;
CGFloat screenWidth = [UIScreen mainScreen].bounds.size.width;
CGFloat screenHeight = [UIScreen mainScreen].bounds.size.height;
UIView* shadowBack = [[UIView alloc]initWithFrame:window.bounds];
shadowBack.backgroundColor = [UIColor blackColor];
shadowBack.alpha = 0.7;
[window addSubview:shadowBack];
UIView* frontWhiteView = [[UIView alloc]initWithFrame:beginFrame];
frontWhiteView.backgroundColor = [UIColor whiteColor];
[window addSubview:frontWhiteView];
NSTimeInterval timeInterval = 0.5;
__weak __typeof(self) weakSelf = self;
[UIView animateWithDuration:timeInterval/5 animations:^{
frontWhiteView.frame = CGRectMake(0, screenHeight/2-18, screenWidth, 36);
} completion:^(BOOL finished) {
[UIView animateWithDuration:4*timeInterval/5 animations:^{
frontWhiteView.frame = CGRectMake(0, 0, screenWidth, screenHeight);
} completion:^(BOOL finished) {
UINavigationController *nav = [[UINavigationController alloc]initWithRootViewController:viewController];
viewController.modalPresentationStyle = UIModalPresentationOverCurrentContext;
nav.modalPresentationStyle = UIModalPresentationOverCurrentContext;
[weakSelf presentViewController:nav animated:NO completion:^{
[shadowBack removeFromSuperview];
[frontWhiteView removeFromSuperview];
}];
// [self.navigationController pushViewController:viewController animated:NO];
// [shadowBack removeFromSuperview];
// [frontWhiteView removeFromSuperview];
}];
}];
[UIView animateWithDuration:timeInterval animations:^{
weakSelf.navigationController.view.transform = CGAffineTransformMakeScale(0.85, 0.85);
} completion:^(BOOL finished) {
weakSelf.navigationController.view.transform = CGAffineTransformIdentity;
}];
}
這里做了一些操作,首先在window上,覆蓋了一個半透明的黑色遮罩,然后又在window上覆蓋了動畫開始的白色方塊。
之后通過動畫,縮小再放大這個白色方塊到鋪滿全屏,動畫完成以后,presentViewController到下一個視圖,注意presentViewController是不再需要動畫了,所以傳入NO
在這個動畫同時,還有一個動畫,它與上面的動畫總時間相同,整個動畫縮小了當前整個視圖的(self.navigationController.view)的大小,有一種下沉的感覺,在動畫結(jié)束的時候,這個時候下一個ViewController也已經(jīng)覆蓋到了當前視圖上,所以恢復當前視圖的大小
這里有一個關(guān)鍵的地方:
viewController.modalPresentationStyle = UIModalPresentationOverCurrentContext;
nav.modalPresentationStyle = UIModalPresentationOverCurrentContext;
這兩句可以保證,下一個視圖覆蓋了當前視圖的時候,當前視圖依然在渲染(具體請Google)
另外,在推入下一個ViewController,我也告訴了下一個VC,他上一個視圖的當前視圖
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
CGFloat screenWidth = [UIScreen mainScreen].bounds.size.width;
CGFloat screenHeight = [UIScreen mainScreen].bounds.size.height;
SecondViewController *secondVC = [[SecondViewController alloc]init];
secondVC.previousNav = self.navigationController;//告訴下一個視圖,它的上一個視圖是誰
[self animToNextViewController:secondVC beginRect:CGRectMake(0, screenHeight/2-20, screenWidth, 40)];
}
這樣設置是為了方便下一個視圖dismiss的時候,依然有一個退回的動畫
下面就說結(jié)束動畫:
- (void)dismissSelf {
if (self.previousNav) {
self.previousNav.view.transform = CGAffineTransformMakeScale(0.85, 0.85);
[UIView animateWithDuration:0.5 animations:^{
self.previousNav.view.transform = CGAffineTransformIdentity;
} completion:^(BOOL finished) {
}];
[self dismissViewControllerAnimated:YES completion:nil];
}else{
[self dismissViewControllerAnimated:YES completion:nil];
}
}
結(jié)束動畫很簡單,如果上一個視圖的屬性不為空,就執(zhí)行定制動畫,否則就執(zhí)行默認動畫
如果可以顯示定制動畫,首先把上一個視圖設置成縮小的樣子,然后在動畫里逐漸放大視圖,知道原樣大小,
這樣就可以流暢完整的實現(xiàn)整個動畫了
如果您有更好的實現(xiàn),或者我這個實現(xiàn)哪里非常耗費性能,還請多多指出,多謝大家。