UIScrollView使用方法详解 (ScrollView半屏滚动)

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代理方法,对内容进行跟踪滚动,可以实现任意距离跟踪滚动,希望有所帮助

UIScrollView使用方法详解 (ScrollView半屏滚动)_第1张图片
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 *)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半屏滚动))