要实现下滑关闭图片这个功能,可以将其分解为几个需求:
- 向下滑动图片
- 图片随着往下滑动会逐渐变小,往上滑动则会还原至初始大小
- 往下滑动背景越来越透明,往上滑动则还原至不透明
滑动图片很简单,添加一个拖拽手势即可:
UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(photoPan:)];
pan.delegate = self;
[imageView addGestureRecognizer:pan];
然后就是实现滑动过程中,图片缩小放大动画以及背景色变化,实现代码如下所示:
-(void)photoPan:(UIPanGestureRecognizer *)panGesture
{
SDBrowserImageView *attchView = (SDBrowserImageView *)panGesture.view;
CGPoint pointTrans = [panGesture translationInView:_scrollView];
CGPoint point = [panGesture locationInView:_scrollView];
NSLog(@"attchView.transform:%@",NSStringFromCGAffineTransform(attchView.transform));
NSLog(@"x:%f , y:%f",point.x,point.y);
if (panGesture.state == UIGestureRecognizerStateBegan)
{
[[UIApplication sharedApplication] setStatusBarHidden:NO];
self.startPoint = point;
}
else if(panGesture.state == UIGestureRecognizerStateChanged)
{
CGFloat deviationY = point.y - _startPoint.y;
CGFloat scaleTrans = 1 - pointTrans.y/SCREEN_HEIGHT;//缩放比例
CGFloat scaleAlpha = (1 - deviationY/SCREEN_HEIGHT) > 0 ? (1 - deviationY/SCREEN_HEIGHT):0.2;//背景色变化比例
self.backgroundColor = [UIColor colorWithWhite:0.1 alpha:scaleAlpha];
if (deviationY > 0)
{
NSLog(@"scaleTrans : %.2f",scaleTrans);
CGAffineTransform trans = CGAffineTransformMakeTranslation(pointTrans.x, pointTrans.y);
CGAffineTransform scale = CGAffineTransformScale(attchView.transform, scaleTrans, scaleTrans);
CGAffineTransform newTransform = CGAffineTransformConcat(trans, scale);
attchView.transform = newTransform;
}
else
{
CGAffineTransform trans = CGAffineTransformTranslate(attchView.transform, pointTrans.x, pointTrans.y);
attchView.transform = trans;
}
}
else if(panGesture.state == UIGestureRecognizerStateEnded)
{
CGFloat deviationY = point.y - _startPoint.y;
if (deviationY >= 60)
{
[self photoPanFinished:attchView];
}
else
{
[UIView animateWithDuration:0.2 animations:^{
attchView.transform = CGAffineTransformIdentity;
}];
}
}
else if(panGesture.state == UIGestureRecognizerStateCancelled)
{
[[UIApplication sharedApplication] setStatusBarHidden:YES];
}
else if(panGesture.state == UIGestureRecognizerStateFailed)
{
[[UIApplication sharedApplication] setStatusBarHidden:YES];
}
//增量置为o
[panGesture setTranslation:CGPointZero inView:attchView];
}
translationInView:
是为了获取每次拖拽间距,往下为正,往上为负,往左为负,往右为正。
startPoint是初始触摸点,locationInView:
是为了获取相对于触摸view的父视图的移动距离。
CGAffineTransformMakeTranslation 是位移变换。
CGAffineTransformScale 是缩放变换。
CGAffineTransformConcat 组合两个动画。
CGAffineTransformIdentity 是动画初始状态。
每次移动一段距离都需要执行setTranslation:
方法,将增直量置为0,否则接下来的移动会叠加之前距离。
在拖拽距离超过60,且松手后,会执行photoPanFinished:
方法以关闭图片。
在查看图片时,实现下滑以关闭图片过程中,碰到一个问题:Pan手势与UIScrollView自带的Pan手势冲突,只能相应下滑关闭手势,不能相应左右滑动手势,解决办法如下:
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
{
if ([gestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]]) {
UIPanGestureRecognizer *pan = (UIPanGestureRecognizer *)gestureRecognizer;
CGPoint pos = [pan velocityInView:pan.view];
if (pos.y > 0) {
return YES;
}
}
return NO;
}
其中velocityInView:是用来获取滑动速度的,pos.y > 0 表示速度向下,反之向上。
这个方法还可以解决如下问题:
- 可以使得向下滑动图片时,scollview不动(只需要多加一行禁用scrollview的代码)
2.使图片初始不能向上滑动,只能向下滑