豌豆莢一覽的轉(zhuǎn)場動畫非常炫啤覆,尤其是點擊一個新聞條目跳轉(zhuǎn)到新聞?wù)牡臅r候
于是我做了個類似的,放在了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
在這個動畫同時优构,還有一個動畫诵叁,它與上面的動畫總時間相同,整個動畫縮小了當(dāng)前整個視圖的(self.navigationController.view)的大小钦椭,有一種下沉的感覺拧额,在動畫結(jié)束的時候,這個時候下一個ViewController也已經(jīng)覆蓋到了當(dāng)前視圖上彪腔,所以恢復(fù)當(dāng)前視圖的大小
這里有一個關(guān)鍵的地方:
viewController.modalPresentationStyle = UIModalPresentationOverCurrentContext;
nav.modalPresentationStyle = UIModalPresentationOverCurrentContext;
這兩句可以保證侥锦,下一個視圖覆蓋了當(dāng)前視圖的時候,當(dāng)前視圖依然在渲染(具體請Google)
另外德挣,在推入下一個ViewController恭垦,我也告訴了下一個VC,他上一個視圖的當(dāng)前視圖
- (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)];
}
這樣設(shè)置是為了方便下一個視圖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í)行默認動畫
如果可以顯示定制動畫,首先把上一個視圖設(shè)置成縮小的樣子懂扼,然后在動畫里逐漸放大視圖禁荸,知道原樣大小,
這樣就可以流暢完整的實現(xiàn)整個動畫了
如果您有更好的實現(xiàn)阀湿,或者我這個實現(xiàn)哪里非常耗費性能赶熟,還請多多指出,多謝大家陷嘴。