杂记-下滑关闭图片

要实现下滑关闭图片这个功能,可以将其分解为几个需求:

  1. 向下滑动图片
  2. 图片随着往下滑动会逐渐变小,往上滑动则会还原至初始大小
  3. 往下滑动背景越来越透明,往上滑动则还原至不透明

滑动图片很简单,添加一个拖拽手势即可:

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 表示速度向下,反之向上。

这个方法还可以解决如下问题:

  1. 可以使得向下滑动图片时,scollview不动(只需要多加一行禁用scrollview的代码)
    2.使图片初始不能向上滑动,只能向下滑

推荐阅读更多精彩内容

  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 7,567评论 4 41
  • 木子手绘阅读 146评论 0 4
  • People always think pregnancy is very easy and happy. ...
    Wu雪梨阅读 79评论 2 0
  • “我喜欢太阳 更喜欢你” 前几天,从通宵的D楼看出去,乏累的视觉让地平面像站立了起来一般,仿佛看不到边界。凌晨四点...
    阳好阅读 231评论 9 5