開始思考上面留下的兩個問題杭煎。
TableView的過渡動畫思路
先從taleView的過渡開始,這個我是做了很多的測試毒返,如果我們把bgView繼承改成TableView的話挤聘,在放大的過程中,cell的高度不會變衣盾,就會橫向拉長寺旺,會很丑,然后再刷地一下恢復正常势决。后來我在約束的設置中引入了Scala參數阻塑,就是根據bgView 和 屏幕寬的 比例,整體把約束乘上這個參數果复,但是效果還是不盡如人意陈莽,從我的感覺來看還是不好看。 就是這么個東西虽抄,感興趣可以試一下走搁,也許再微調一下效果就比較好。
((ScreenWidth * (3.0 / 5)) / ScreenWidth)
后來我思考我們既然可以拿到下一個控制器迈窟,那就是說可以把下個控制器里的tableview按一定的高度截成圖朱盐,然后在轉場里面?zhèn)鬟f給bgView,這樣就是可以很完美的匹配菠隆,但是在開始之初,因為collectionViewCell的寬高比的原因,就拉長的不大好骇径,但是我們可以把這個cell的寬高調整一下躯肌,這樣效果應該就會好。
總體來說破衔,這兩個思路都是可行的清女,但是又懶得大改了,所以我再嘗試后晰筛,就先放著嫡丙,后來做完頭像移動后,覺得好像不用這個也還行读第,就沒做曙博,可以自行去嘗試一下。
所以接下去怜瞒,我們繼續(xù)講頭像移動
CAKeyframeAnimation關鍵幀動畫
UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage circleImage:[NSString stringWithFormat:@"%ld",(i + 1) * 10]]];
imageView.frame = CGRectMake(0, 0, 30, 30);
imageView.center = point;
UIWindow *keyW = [UIApplication sharedApplication].keyWindow;
[keyW addSubview:imageView];
CAKeyframeAnimation *anim = [CAKeyframeAnimation animationWithKeyPath:@"position"];
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:point];
CGPoint endP = CGPointFromString(_arrM[i]);
[path addLineToPoint:endP];
anim.path = path.CGPath;
anim.duration = AnimationDuration;
anim.delegate = self;
imageView.center = endP;
[anim setValue:imageView forKey:@"LL"];
[imageView.layer addAnimation:anim forKey:nil];
這個動畫在我們應用起來就有幾個難點父泳,因為我們不用考慮曲線問題,也是那個貝塞爾點是不用計算指定的吴汪,只要起點和終點惠窄,但是就起點和終點而言,都由于嵌套深的緣故漾橙,他們的位置都不好獲取杆融,所以就要想點辦法
UIWindow *keyW = [UIApplication sharedApplication].keyWindow;
- (CGRect)convertRect:(CGRect)rect toView:(nullable UIView *)view;
通過這兩個方法,來計算某個控件在父控件中的位置相對于大屏幕的位置是比較常見的霜运,但是它們有一個缺陷脾歇,就是只能用來計算嵌套相對較少的情況,深的話會不準觉渴,我呢介劫,就比較懶,我就用這套方法案淋,反復試驗了幾次座韵,找到了在collectionViewCell里面的用戶視圖的位置,但是這個位置x是可以直接的獲取踢京,y的話獲取以后要加一個cell的高度然后還有一個 -12的偏移誉碴,要是屏幕適配的話,應該去 -12可能會有不同瓣距,測試一下黔帕,加個版本判斷也是可以的,因為這是個耗時的操作蹈丸,所以我就直接用了這個結果成黄,90 + i * 25, 141 + (ScreenHeight * (5.0 / 9))矛物,但是我是推薦不要用這種魔法數字,當然我是獲取到的践盼,因為比較懶就直接用結果了环础,哈哈。
然后后面我們要解決的是終點的位置闻伶,我們起初用的是UITableViewAutomaticDimension這個東西在自動計算行高的滨攻,但是這樣算完他不會給行高具體是多少,所以我們就要修改一下蓝翰,用那種自己算的方法來光绕,自己算就是算個評論的高度,用這個就行
CGSize size = [model.userComment boundingRectWithSize:CGSizeMake(ScreenWidth - 15, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:14]} context:nil].size;
然后我們在模型的set方法里面進行更新初始化的約束,但是不要直接把UI初始化放在里面畜份,會有復用的問題诞帐,僅僅根據size.height更新一下高度約束就好
[self.userComment mas_updateConstraints:^(MASConstraintMaker *make) {
make.height.equalTo(@(size.height));
}];
但是因為我們用的是約束這種東西,他們比frame運算靠后漂坏,所以比較麻煩景埃,還好有個layoutIfNeeded,我們在更新完約束以后顶别,調用一下這個方法谷徙,讓他直接算出來位置,不然的話驯绎,當時是沒辦法獲取位置的
[self layoutIfNeeded];
之后我們就可以用個屬性把它的高度獲取到傳遞到外面
- (CGFloat)cellHeight
{
return CGRectGetMaxY(self.userComment.frame) + 15;
}
然后我們在控制器的返回行高的方法里完慧,獲取到行高,計算頭像位置剩失,存到一個數組里面屈尼,這樣我們就可以在轉場動畫里面把這個數組獲取到
- (NSMutableArray *)calculatePicCenter
{
NSMutableArray *arr = [NSMutableArray arrayWithCapacity:4];
CGFloat start = TitleViewHeight + TopViewHeight;
CGFloat centerX = 30;
for (NSInteger i = 0; i < 4; i++) {
CGFloat centerY = start + 10 + 15;
[arr addObject:NSStringFromCGPoint(CGPointMake(centerX, centerY))];
start += [self.arrCellHeight[i] floatValue];
}
return arr;
}
然后就可以順利的去實現我們的動畫,執(zhí)行完成以后把圖片移除就好了拴孤。
- (void)animation:(NSInteger)count
{
//90 + i * 25, 141 + (ScreenHeight * (5.0 / 9)) 脾歧?
for (NSInteger i = 0; i < count; i++) {
CGPoint point = CGPointMake(90 + i * 25, 141 + (ScreenHeight * (5.0 / 9)));
UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage circleImage:[NSString stringWithFormat:@"%ld",(i + 1) * 10]]];
imageView.frame = CGRectMake(0, 0, 30, 30);
imageView.center = point;
UIWindow *keyW = [UIApplication sharedApplication].keyWindow;
[keyW addSubview:imageView];
CAKeyframeAnimation *anim = [CAKeyframeAnimation animationWithKeyPath:@"position"];
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:point];
CGPoint endP = CGPointFromString(_arrM[i]);
[path addLineToPoint:endP];
anim.path = path.CGPath;
anim.duration = AnimationDuration;
anim.delegate = self;
imageView.center = endP;
[anim setValue:imageView forKey:@"LL"];
[imageView.layer addAnimation:anim forKey:nil];
}
}
//動畫停止的代理
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag
{
//從anim中取出圖片,移除
UIImageView *imgV = [anim valueForKey:@"LL"];
[imgV removeFromSuperview];
}
還有一個細節(jié)性的問題演熟,就是這樣的話鞭执,我們轉場的時候原有的用戶視圖還是會存在的,這是因為我們之前約束芒粹,層次的關系兄纺,即便我們讓它隱藏,也得是再執(zhí)行完動畫才能隱藏化漆,所以要做的就是在對應的位置更改用戶頭像的約束估脆,讓它直接依附于shadowView,然后就可以在這里直接隱藏了座云,這樣我們的動畫就算基本完成了疙赠。
效果是這樣的:
現在還存在幾個問題付材,就是留給別人去處理的,我要去做正事了棺聊,哈哈伞租,當然都是小問題
1.:我的模擬器iphone7上的轉場會有問題,我因為很長時間不動這套了限佩,不知道他們有什么變化沒,所以可以看看
2.:上面談到的頭像移動的起始位置的魔法值的問題
3.: 那個TableView過渡動畫添加的問題
4.:把數據甩出去裸弦,正正經經做個對接口
5.:代碼沒有實體文件夾祟同,很亂
我的代碼放在鏈接: https://pan.baidu.com/s/1VruBLLZY9htHhI5wIMpfPg 密碼: sywf ,是里面是對應這個目錄的五份代碼理疙,其實前面的3份自己去實現都是比較容易的晕城。
另外,就是在后面可能(- -窖贤。等我有空吧)砖顷,會更新一些別的,比如一些現在app里面好玩的效果功能赃梧,還有大型框架的邏輯滤蝠,仿寫這些。授嘀。