折疊效果.gif
界面分析
- 手指在圖片上拖拽,圖片的上半部分能夠跟隨手指的移動產(chǎn)生一個旋轉(zhuǎn)的效果.
- 向下拖拽的時候,圖片的下半部分會有陰影產(chǎn)生.
- 在手指松開的時候,恢復(fù)到初始狀態(tài),并且產(chǎn)生1個回彈效果.
界面實現(xiàn)
在一個imageView 上面對圖片進行變換操作,顯然不太現(xiàn)實.可以使用兩個imageView上下拼接在一起,使用1個大view作為容器裝置兩個imageView.
Snip20160501_4.png
給這個view綁定類
創(chuàng)建折疊view的類
所以現(xiàn)在必須在上面的imageView顯示圖片的上半部分,在下面的imageView顯示圖片的下半部分.
有兩種方式可以實現(xiàn)
- 第一種方式
在storyboard中設(shè)置頂部imageView的contentMode 為top,底部imageView的contentMode為bottom.
Snip20160501_7.png
這樣設(shè)置完之后看起來就像是拼接成的一整張圖片了.但是使用這種方式設(shè)置完之后,由于圖片的大小是超過imageView的大小的.并且旋轉(zhuǎn)的坐標軸是整個view的中心位置,所以使用這種方式憑借的話還需要做一些配置
- (void)awakeFromNib {
self.topImageView.layer.masksToBounds = YES;
self.bottomImageView.layer.masksToBounds = YES;
//設(shè)置錨點
self.topImageView.layer.anchorPoint = CGPointMake(0.5, 1);
}
由于重新設(shè)置了錨點 所以此時運行程序界面會變成這樣
修改錨點之后
重新布局使界面正確正確顯示
- (void)layoutSubviews {
[super layoutSubviews];
self.topImageView.layer.frame = CGRectMake(0, 0, self.bounds.size.width, self.bounds.size.height);
}
修改完之后
修改完之后
- 2 第二種方式比較簡單.使用layer自帶的一個屬性contentsRect .
不用設(shè)置contentMode屬性,只需要在
- (void)awakeFromNib {
//contentsRect 取值范圍為 0 - 1
self.topImageView.layer.contentsRect = CGRectMake(0, 0, 1, 0.5);
self.bottomImageView.layer.contentsRect = CGRectMake(0, 0.5, 1, 0.5);
//設(shè)置錨點 讓topImageView可以繞著底部旋轉(zhuǎn)
self.topImageView.layer.anchorPoint = CGPointMake(0.5, 1);
//給foldView 添加拖拽手勢
UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(pan:)];
[self addGestureRecognizer:pan];
// 利用`CAGradientLayer`(漸變圖層)制作陰影效果,添加到底部視圖上,并且一開始需要隱藏,在拖動的時候慢慢顯示出來。
// 顏色應(yīng)是由`透明到黑色`漸變,表示陰影從無到有。
CAGradientLayer *gradientLayer = [CAGradientLayer layer];
//漸變圖層的顏色組屬性
gradientLayer.colors = @[(id)[UIColor clearColor].CGColor,(id)[UIColor blackColor].CGColor];
//設(shè)置圖層frame
gradientLayer.frame = self.bottomImageView.bounds;
//設(shè)置圖層不透明度
gradientLayer.opacity = 0;
//設(shè)置漸變的起點 取值范圍為 0 - 1
gradientLayer.startPoint = CGPointMake(0.5, 1);
//設(shè)置漸變終點
gradientLayer.endPoint = CGPointMake(0.5, 0);
//添加圖層
[self.bottomImageView.layer addSublayer:gradientLayer];
//給foldView添加屬性引用圖層
self.gradientLayer = gradientLayer;
}
//重新布局
- (void)layoutSubviews {
[super layoutSubviews];
self.topImageView.layer.frame = CGRectMake(0, 0, self.bounds.size.width, self.bounds.size.height * 0.5);
}
實現(xiàn)拖拽監(jiān)聽方法
- (void)pan:(UIPanGestureRecognizer *)pan {
//手指拖拽的距離
CGPoint offset = [pan translationInView:self];
//寬度
CGFloat height = self.bounds.size.height * 0.5;
// 計算Y軸每偏移一點,需要旋轉(zhuǎn)多少角度,angle = offsetY * M_PI / width;
CGFloat angle = offset.y / height * M_PI ;
// 在拖動的時候計算不透明度值,假設(shè)拖動bottomImageView的一半時,陰影完全顯示,不透明度應(yīng)該為1,因此 opacity = y軸偏移量 * 1 / 200.0;
CGFloat opacity = offset.y * 1.0 / height;
if(pan.state == UIGestureRecognizerStateEnded) {//拖拽停止的時候
//彈簧動畫
[UIView animateWithDuration:0.25 delay:0 usingSpringWithDamping:0.5 initialSpringVelocity:9 options:UIViewAnimationOptionCurveEaseInOut animations:^{
//手指停止拖拽的時候重置圖層形變
self.topImageView.layer.transform = CATransform3DIdentity;
} completion:^(BOOL finished) {
}];
//將漸變層的不透明度改為0(透明).
self.gradientLayer.opacity = 0;
}else {
//初始化
CATransform3D trans = CATransform3DIdentity;
//設(shè)置M34就有立體感(近大遠小)。 -1 / z ,z表示觀察者在z軸上的值,z越小,看起來離我們越近,東西越大。
trans.m34 = 1 / 1000.0;
//設(shè)置繞x軸旋轉(zhuǎn)
self.topImageView.layer.transform = CATransform3DRotate(trans, angle, 1, 0, 0);
//設(shè)置不透明度
self.gradientLayer.opacity = opacity;
}
}