開門見山强法,先看效果圖:
自定義轉(zhuǎn)場動(dòng)畫.gif
自定義 UIViewController Present 樣式摩桶,shrinking bubble 收縮和擴(kuò)張的泡沫赴精。動(dòng)畫來源于
https://github.com/andreamazz/BubbleTransition
對(duì)此進(jìn)行了一些改進(jìn):
1. 把 swift 源碼翻譯成 OC
2. 改進(jìn)了一些動(dòng)畫機(jī)制完沪,具體如下
BubbleTransition效果圖.gif
從它給的效果圖來看息尺,升縮的效果非常贊 (~ ̄▽ ̄~) ——
但是携兵。。
聰明的你可能已經(jīng)看見了搂誉,圖中的兩個(gè) ViewController 背景就是純色徐紧,上面沒任何其他 View,所以顯得效果很贊炭懊。接下來我們看一下加上 View 的效果——
背景添加了一張圖片.gif
這就尷尬了 a( ̄3 ̄)a ——
利用 Reveal 我們看看 View 的層次結(jié)構(gòu)并级。
Reveal結(jié)果.png
中間那一層遠(yuǎn)大于375 x 667的 View 很引人注目呀 (#-.-)——
再來看看代碼:
//計(jì)算一些關(guān)鍵point和frame
CGPoint originalCenter = presentedControllerView.center;
CGSize originalSize = presentedControllerView.frame.size;
CGFloat lengthX = fmax(self.startPoint.x, originalSize.width - self.startPoint.x);
CGFloat lengthY = fmax(self.startPoint.y, originalSize.height - self.startPoint.y);
CGFloat offset = sqrt(lengthX * lengthX + lengthY * lengthY) * 2;
CGSize size = CGSizeMake(offset, offset);
//上圖中的大View,先縮小到最小侮腹,再用UIView的動(dòng)畫變大嘲碧,設(shè)置cornerRadius變成圓,然后漏出下面的VC的view
self.bubble = [[UIView alloc] initWithFrame:CGRectMake(0, 0, size.width, size.height)];
self.bubble.layer.cornerRadius = size.height/2.0f;
self.bubble.center = self.startPoint;
self.bubble.transform = CGAffineTransformScale(CGAffineTransformIdentity, 0.001, 0.001);
self.bubble.backgroundColor = self.bubbleColor;
[containerView addSubview:self.bubble];
//上層VC的View
presentedControllerView.center = self.startPoint;
presentedControllerView.transform = CGAffineTransformScale(CGAffineTransformIdentity, 0.001, 0.001);
presentedControllerView.alpha = 0;
[containerView addSubview:presentedControllerView];
[UIView animateWithDuration:self.duration animations:^{
self.bubble.transform = CGAffineTransformIdentity;
presentedControllerView.transform = CGAffineTransformIdentity;
presentedControllerView.alpha = 1;
presentedControllerView.center = originalCenter;
} completion:^(BOOL finished) {
[transitionContext completeTransition:finished];
}];
注釋中解釋了動(dòng)畫原因父阻。主要的原理是View的層級(jí)關(guān)系愈涩,通過上層 bubble 這個(gè) View,慢慢變大至非,形成圓擴(kuò)大的動(dòng)畫钠署。但有一個(gè)前提是,下層的 View的背景色和bubble同色荒椭,混合之后谐鼎,才能形成完整的動(dòng)畫,一旦下層 View 有“噪點(diǎn)”趣惠,這個(gè)動(dòng)畫就失效了狸棍。就像上面的gif展示的一樣。
改進(jìn)
既然原代碼是通過上下層 View 來實(shí)現(xiàn)味悄,那讓咱們換個(gè)思路草戈,只需要修改一點(diǎn)點(diǎn)代碼就可以——
iOS不是還有一個(gè)好玩的東西,叫做 maskView 的嗎侍瑟?
CGPoint originalCenter = presentedControllerView.center;
CGSize originalSize = presentedControllerView.frame.size;
CGFloat lengthX = fmax(self.startPoint.x, originalSize.width - self.startPoint.x);
CGFloat lengthY = fmax(self.startPoint.y, originalSize.height - self.startPoint.y);
CGFloat offset = sqrt(lengthX * lengthX + lengthY * lengthY) * 2;
CGSize size = CGSizeMake(offset, offset);
self.bubble = [[UIView alloc] initWithFrame:CGRectMake(0, 0, size.width, size.height)];
self.bubble.backgroundColor = [UIColor redColor];
self.bubble.layer.cornerRadius = size.height/2.0f;
self.bubble.center = self.startPoint;
self.bubble.transform = CGAffineTransformScale(CGAffineTransformIdentity, 0.001, 0.001);
//將上層 bubble 當(dāng)做下層 View 的 maskView
containerView.maskView = self.bubble;
presentedControllerView.center = originalCenter;
[containerView addSubview:presentedControllerView];
[UIView animateWithDuration:self.duration animations:^{
self.bubble.transform = CGAffineTransformIdentity;
} completion:^(BOOL finished) {
[transitionContext completeTransition:finished];
}];
Github鏈接:
https://github.com/Balzac646729740/WHBubbleTransition