下面的gif是我在動(dòng)畫網(wǎng)站上看到比較好看的動(dòng)畫瞭空,然后我就想試著自己寫出這個(gè)動(dòng)畫始鱼。
下面是我試著實(shí)現(xiàn)動(dòng)畫的gif
先說說我實(shí)現(xiàn)原型動(dòng)畫中那些不足的地方吧臀防!
- 界面的層次結(jié)構(gòu)不是很明顯为流,主要沒有去實(shí)現(xiàn)弧形的漸變酸茴。
- 沒有實(shí)現(xiàn)cell的滑動(dòng)刪除。
- 如果你看了代碼后沼本,我這只適配了一種動(dòng)畫噩峦,而沒有適配一種通用的動(dòng)畫。
接著我們說說我這個(gè)動(dòng)畫用到那些知識(shí)吧抽兆!
- 界面的幾個(gè)部分View的層次結(jié)構(gòu)识补,涉及到陰影和layer層的zPosition.
- 自定義的UICollectionView和UITableView。
- 動(dòng)畫的書寫和其先后執(zhí)行辫红。
- View的center算法
代碼我會(huì)放在我github上凭涂,在這兒我就對(duì)其中一些比較難實(shí)現(xiàn)的部分說明一下吧。
]
圖層的3D結(jié)構(gòu)
代碼:
_suspendView = [[SuspendView alloc]
initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH/5.0, 130)];
_suspendView.top = self.topView.bottom;
_suspendView.centerX = self.topView.centerX;
_suspendView.layer.shadowColor = [UIColor blackColor].CGColor;
_suspendView.layer.shadowOffset = CGSizeMake(-4, 8);
_suspendView.layer.shadowOpacity = 0.8;
_suspendView.layer.shadowRadius = 4;
_suspendView.backgroundColor = SUSPEND_COLOR;
_suspendView.layer.zPosition = 2;
_weekView = [[DynamicWeekView alloc] initWithFrame:CGRectMake(0, self.topView.bottom, SCREEN_WIDTH, 120) collectionViewLayout:layout];
_weekView.layer.shadowColor = [UIColor blackColor].CGColor;
_weekView.layer.shadowOffset = CGSizeMake(4, 8);
_weekView.layer.shadowOpacity = 0.8;
_weekView.layer.shadowRadius = 4;
_weekView.layer.zPosition = 1;
_topView = [[UIView alloc]initWithFrame:CGRectMake(0, 20, SCREEN_WIDTH, 44)];
_topView.layer.shadowColor = [UIColor blackColor].CGColor;
_topView.layer.shadowOffset = CGSizeMake(4, 8);
_topView.layer.shadowOpacity = 0.8;
_topView.layer.shadowRadius = 4;
_topView.backgroundColor = TOPBG_COLOR;
_topView.layer.zPosition = 3;
[self.view addSubview:self.weekView];
[self.view addSubview:self.suspendView];
[self.view addSubview:self.topView];
可以看到在同一個(gè)視圖添加別的View贴妻,如果想要實(shí)現(xiàn)視圖的層次感切油,
就需要加上陰影和 View.layer.zPosition = number;這樣就可以去實(shí)現(xiàn)結(jié)構(gòu)層次。
在自定義UICollectionView后滑動(dòng)時(shí)只是移動(dòng)一個(gè)cell的距離名惩。
代碼:
self.gestureRecognizers = nil;
UISwipeGestureRecognizer *gestureLeft = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(collectionViewSwipped:)];
gestureLeft.direction = UISwipeGestureRecognizerDirectionLeft;
UISwipeGestureRecognizer *gestureRight = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(collectionViewSwipped:)];
gestureRight.direction = UISwipeGestureRecognizerDirectionRight;
[self addGestureRecognizer:gestureLeft];
[self addGestureRecognizer:gestureRight];
這樣就可以屏蔽UICollectionView原有的滑動(dòng)手勢(shì)澎胡。
float space = 0;
float viewWidth = SCREEN_WIDTH/5.0;
//滑動(dòng)的時(shí)候判斷
if (self.contentSize.width - self.contentOffset.x - SCREEN_WIDTH/5.0 < SCREEN_WIDTH) {
self.contentSize = CGSizeMake(self.contentSize.width + SCREEN_WIDTH/5.0 * 2,
SCREEN_WIDTH/5.0 - 10);
}
[self scrollRectToVisible:CGRectMake((self.currentIdx - 2) * (viewWidth + space),
0,
self.frame.size.width,
self.frame.size.height)
animated:YES];
這段代碼主要是滑動(dòng)后cell會(huì)移動(dòng)一個(gè)cell距離,但需要注意的是分別取處理兩端的時(shí)候的滑動(dòng)娩鹉。
動(dòng)畫:在這里只有視圖的frame攻谁,center,以及alpha變化的動(dòng)畫弯予。View層做動(dòng)畫一般是frame.alpha的動(dòng)畫戚宦,只需要放在蘋果官方的方法中去實(shí)現(xiàn)即可。而當(dāng)需要自定義動(dòng)畫時(shí)就需要layer層去做處理熙涤,去設(shè)置其中的路徑阁苞,這時(shí)的路徑一般貝塞爾曲線完成,然后放在一個(gè)動(dòng)畫對(duì)象中去實(shí)現(xiàn)祠挫。
當(dāng)然這里的動(dòng)畫知識(shí)View層的變化那槽。可以用一組幀動(dòng)畫去實(shí)現(xiàn)等舔,其中有cell的點(diǎn)擊動(dòng)畫-->logo的彈出動(dòng)畫-->利用layer層和貝塞爾生成圓圈動(dòng)畫-->logo的運(yùn)行動(dòng)畫骚灸。
部分代碼:
[UIView animateWithDuration:0.4 delay:0 usingSpringWithDamping:0.8 initialSpringVelocity:0 options:0 animations:^{
self.coverView.alpha = 0.4;
centerBtn.center = CGPointMake(SCREEN_WIDTH/2.0, 2*SCREEN_HEIGHT/3.0);
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.5 delay:0 usingSpringWithDamping:0.8 initialSpringVelocity:0 options:0 animations:^{
[ExpandModel expandToNewCenterWithViews:self.logoBtnArr andCenterP:centerBtn.center];
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.3 animations:^{
[self.circleLayer setStrokeColor:[UIColor yellowColor].CGColor];
}];
}];
}];
這個(gè)logo運(yùn)動(dòng)后cented的確定,因?yàn)楫?dāng)滑動(dòng)tableView后慌植,得根據(jù)contentoffset去確定logo運(yùn)動(dòng)到你點(diǎn)擊的cell上甚牲,這個(gè)時(shí)候利用contentoffset去實(shí)現(xiàn)。
NSIndexPath *indexPath = [weakSelf.tableView indexPathForCell:weakSelf.scheduleCell];
CGFloat y = (indexPath.row + 1) * weakSelf.scheduleCell.height + tableView.bottom - weakSelf.contentOffY - weakSelf.scheduleCell.height/2.0;
其余就是一些基礎(chǔ)的代碼的書寫了蝶柿,例如點(diǎn)擊后需要傳出的參數(shù)丈钙,視圖的創(chuàng)建封裝等。
最后附上代碼地址:https://github.com/CoDancer/DynamicSchedule