美文网首页iOS Dev
UIScrollView使用方法详解 (ScrollView半屏

UIScrollView使用方法详解 (ScrollView半屏

作者: 不_才 | 来源:发表于2016-07-29 20:37 被阅读0次

    UIScrollView 详解

    UIScrollView全解
    最近看到一篇10年的老帖讨论几年Scroll的半屏滚动效果,正好闲来无事,对Scroll进行了比较详细的整理实现,文章后半部分实现了用基础方法实现的解决方案

    基础知识

    - (void)createScrollView{
        _scrollView = [[UIScrollView alloc] initWithFrame:self.view.frame];
        UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"image"]];
        imageView.userInteractionEnabled = YES;
        //imageview对象添加到scrollview上
        [_scrollView addSubview:imageView];
        
        //设置scrollview内容的尺寸
        _scrollView.contentSize = imageView.bounds.size;
        //设置内容的偏移量,contentOffset参照contentSize的坐标系
        _scrollView.contentOffset = CGPointMake(1000, 500);
        //设置是否回弹
        _scrollView.bounces = YES;
        
        //设置内容的边距
        _scrollView.contentInset = UIEdgeInsetsMake(10, 10, 10, 10);
        //设置是否可以滚动
        _scrollView.scrollEnabled = YES;
        //是否可以滚动到内容的顶部(点击状态栏)
        _scrollView.scrollsToTop = YES;
        
        //按页滚动
        _scrollView.pagingEnabled =YES;
        
        //是否显示水平和垂直方向的指示器
        _scrollView.showsHorizontalScrollIndicator = YES;
        _scrollView.showsVerticalScrollIndicator = YES;
        //设置指示器的样式
        _scrollView.indicatorStyle = UIScrollViewIndicatorStyleWhite;
        
        //设置代理
        _scrollView.delegate = self;
        
        CGFloat imageWidth = imageView.frame.size.width;
        
        //设置最小和最大缩放比例
        _scrollView.minimumZoomScale = WIDTH / imageWidth;
        _scrollView.maximumZoomScale = 1.5;
        
        
        [self.view addSubview:_scrollView];
        
        //给UIImageView添加手势
        UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(imageViewTapGesture:)];
        tap.numberOfTapsRequired = 2;
        [imageView addGestureRecognizer:tap];
    }
    

    代理使用

    UIScrollView 有自己的代理方法,在代理方法中有相当全面的调用时机,借用代理方法可以制作多种,scrollerView的高级使用

    #pragma mark - UIScrollViewDelegate
    //只要发生滚动,就会调用该方法
    - (void)scrollViewDidScroll:(UIScrollView *)scrollView{
    //    NSLog(@"scrollview滚动");
    }                                               // any offset changes
    
    //只要zoomScale发生变化,就会调用该方法
    - (void)scrollViewDidZoom:(UIScrollView *)scrollView{
        NSLog(@"发生缩放");
    } // any zoom scale changes
    
    // called on start of dragging (may require some time and or distance to move)
    - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView{
        NSLog(@"开始拖动");
    }
    // called on finger up if the user dragged. velocity is in points/millisecond. targetContentOffset may be changed to adjust where the scroll view comes to rest
    - (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset{
        NSLog(@"将要结束拖动");
    }
    // called on finger up if the user dragged. decelerate is true if it will continue moving afterwards
    - (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate{
        NSLog(@"拖动结束");
    }
    
    - (void)scrollViewWillBeginDecelerating:(UIScrollView *)scrollView{
        NSLog(@"将要开始减速");
    }   // called on finger up as we are moving
    - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView{
        NSLog(@"减速结束");//停止滚动
    }      // called when scroll view grinds to a halt
    
    - (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView{
        NSLog(@"滚动动画结束");
    } // called when setContentOffset/scrollRectVisible:animated: finishes. not called if not animating
    
    - (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView{
        //返回可以进行缩放的子视图
        return scrollView.subviews[0];
    }     // return a view that will be scaled. if delegate returns nil, nothing happens
    - (void)scrollViewWillBeginZooming:(UIScrollView *)scrollView withView:(nullable UIView *)view {
        NSLog(@"将要开始缩放");
    
    } // called before the scroll view begins zooming its content
    - (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(nullable UIView *)view atScale:(CGFloat)scale{
        NSLog(@"缩放结束");
        NSLog(@"%@", view);
    
    #if 0
        //恢复原来大小的时候,可能存在问题
        if(scale < 1.0){
            CGPoint center = view.center;
            center.y = HEIGHT / 2;
            view.center = center;
        }
    #else
        if (view.frame.size.width > WIDTH) {
            scrollView.contentInset = UIEdgeInsetsMake(0, 0, 0, 0);
        }else{
            [UIView animateWithDuration:0.5 animations:^{
                scrollView.contentInset = UIEdgeInsetsMake((HEIGHT - view.frame.size.height) / 2, 0, 0, 0);
            }];
        }
        
        
    #endif
        
    } // scale between minimum and maximum. called after any 'bounce' animations
    
    - (BOOL)scrollViewShouldScrollToTop:(UIScrollView *)scrollView{
        //scrollToTop = YES,才会调用该方法
        //返回YES,可以滚动到顶部;NO 不可以
        return YES;
    }   // return a yes if you want to scroll to the top. if not defined, assumes YES
    - (void)scrollViewDidScrollToTop:(UIScrollView *)scrollView{
        NSLog(@"滚动到顶部");
    }      // called when scrolling animation finished. may be called immediately if already at top
    

    拓展使用 —— ScrollView制作仿乐乎半屏滚动效果

    对于ScrollView的半屏滚动,由于PagEnable打开以后只能根据scrollView本身的高宽进行按页滚动,实现原理主要是调用DidScroll代理方法,对内容进行跟踪滚动,可以实现任意距离跟踪滚动,希望有所帮助

    123.gif
    - (instancetype)initWithFrame:(CGRect)frame
    {
        self = [super initWithFrame:frame];
        if (self) {
            rateDistance = 380;
            _imagetViewArr = [[NSMutableArray alloc]init];
            self.delegate = self;
            self.contentOffset = CGPointMake(0, 0);
            
        }
        return self;
    }
    
    -(void)setImagetViewArr:(NSMutableArray *)imagetViewArr
    {
        _imagetViewArr = imagetViewArr;
        [self creatMainview];
    }
    
    -(void)creatMainview
    {
        self.contentSize = CGSizeMake(self.frame.size.width * _imagetViewArr.count, self.frame.size.height);
        moverate = 0;
        NSLog(@"%lu",(unsigned long)_imagetViewArr.count);
        self.pagingEnabled = YES;
        self.showsHorizontalScrollIndicator = NO;
        self.showsVerticalScrollIndicator = NO;
        [self SetImagerView];
        
    }
    
    -(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
    {
        UITouch * evt = [touches anyObject];
        CGPoint point = [evt locationInView:self];
        CGFloat wide = self.frame.size.width;
        CGFloat x1 = self.contentOffset.x + wide;
        CGFloat x2 = self.contentOffset.x - wide;
        if(point.x - moverate >= self.frame.size.width * 0.79 && point.x < self.frame.size.width * 7)
        {
            [UIView animateWithDuration:0.2 animations:^{
    
                self.contentOffset = CGPointMake(x1, 0);
                    [self scrollViewDidScroll:self];
            } completion:^(BOOL finished) {
            }];
        }
        else if(point.x - moverate <= self.frame.size.width * 0.21 && point.x > self.frame.size.width*0.25)
        {
            [UIView animateWithDuration:0.2 animations:^{
               self.contentOffset = CGPointMake(x2, 0);
                    [self scrollViewDidScroll:self];
            } completion:^(BOOL finished) {
               
            }];
        }
        
        [self scrollViewDidScroll:self];
    }
    
    -(void)SetImagerView
    {
        ImageXarr = [[NSMutableArray alloc]init];
        
        int ii = (int)_imagetViewArr.count;
        for (int i = 0 ; i < ii; i++) {
            UIImageView * imageView = [[UIImageView alloc]initWithFrame:CGRectMake(self.frame.size.width / _imagetViewArr.count * i, 0, self.frame.size.width * 0.6  , self.frame.size.width * 0.5)];
            imageView.center = CGPointMake((self.frame.size.width*0.6)/2 * (2 * i + 1.67) , self.frame.size.height/2.0);
            //设置背景
            CALayer * layer = [imageView layer];
    //        边框
    //        layer.borderColor = [[UIColor blackColor]CGColor];
    //        layer.borderWidth = 5;
    //        阴影
            layer.shadowColor = [[UIColor blackColor]CGColor];
            layer.shadowOffset = CGSizeMake(10, 5);
            layer.shadowRadius = 10;
            layer.shadowOpacity = 0.5;
            
    //        layer.cornerRadius = 40;
    //        layer.masksToBounds = YES;
            
            imageView.backgroundColor = [UIColor redColor];
            [imageView sd_setImageWithPreviousCachedImageWithURL:_imagetViewArr[i] placeholderImage:[UIImage imageNamed:@"arrow"] options:2 progress:^(NSInteger receivedSize, NSInteger expectedSize) {
                
            } completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
               
    //            float reat = image.size.height / image.size.width;
                
               // imageView.frame = CGRectMake(imageView.frame.origin.x, imageView.frame.origin.y, imageView.frame.size.width, imageView.frame.size.height * reat);
               
            }];
            
            
            
            
            imageView.tag = i + 100;
            //[_imagetViewArr addObject:imageView];
            [self addSubview:imageView];
        };
        
        [self scrollViewDidScroll:self];
    }
    
    -(void)scrollViewDidScroll:(UIScrollView *)scrollView
    {
        CGFloat rate;
        CGFloat reduce;
        
        reduce = moverate - scrollView.contentOffset.x;
        
        moveNum += reduce;
        //NSLog(@"%f",reduce);
        for (int i = 0 ; i < _imagetViewArr.count; i++) {
            
            UIView * view = [self viewWithTag:100 + i];
            CGFloat distance = fabs(scrollView.contentOffset.x + self.frame.size.width/2  - view.center.x);
            
            CGFloat ratex = view.center.x - reduce * 0.4;
            
            view.center = CGPointMake(ratex,view.center.y);
            
            if (distance >= rateDistance)
                rate = 0.7;
            else
                rate =  (rateDistance - distance*0.2) / (rateDistance ) ;
           
            view.transform = CGAffineTransformMakeScale(rate, rate);
        }
           moverate = scrollView.contentOffset.x;
        
    }
    

    相关文章

      网友评论

        本文标题:UIScrollView使用方法详解 (ScrollView半屏

        本文链接:https://www.haomeiwen.com/subject/gkizjttx.html