iOS UIScrollView的宽度不是整数导致的精度丢失

问题

如图,轮播图每次拖动到第二个图片的时候,就会返回到第一张图片
请添加图片描述

初始化代码

在这里插入代码片- (UIScrollView *)contentScrollView
{
    
    
    if (!_contentScrollView) {
    
    
        _contentScrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, CGRectGetWidth(self.bounds), CGRectGetHeight(self.bounds))];
        _contentScrollView.contentSize = CGSizeMake(3 * CGRectGetWidth(self.bounds), CGRectGetHeight(self.bounds));
        _contentScrollView.delegate = self;
        _contentScrollView.pagingEnabled = YES;
        _contentScrollView.showsHorizontalScrollIndicator = NO;
    }
    return _contentScrollView;
}

原因

在scrollView的宽度不是整数的时候,获取偏移量有误差
如图,之前为了使轮播图能够支持双手交替快速拖动,在

  • (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
    方法中添加的 如下代码
    请添加图片描述

在frame 是整数的时候没有问题

如图
请添加图片描述

请添加图片描述

但是当frame 宽度不是整数的时候,就产生了开始图示的问题

请添加图片描述

解决方法,添加数值误差容错

请添加图片描述
代码

- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
    
    
    self.isDragging = YES;
    [self pause];
    NSInteger count = self.numberOfLoopView;
    /*
     注意
     1这里如果 scrollView.contentOffset.x 不等于 CGRectGetWidth(scrollView.bounds),说明
     开始拖动的时候scrollView还没有回归到中间位置,而我们每次都是
     在 scrollViewDidEndDecelerating 方法中进行修改当前索引并且重置回中间偏移量CGRectGetWidth(scrollView.bounds)的,
     这里偏移量 不是CGRectGetWidth(scrollView.bounds) ,说明拖动过之后, scrollViewDidEndDecelerating 还没有执行
     就立即进行下一次拖动了,这就需要我们手动调用一下 scrollViewDidEndDecelerating 要进行但尚未进行的的操作,保证我们的 当前展示数据正确。
     
     2这里不需要担心第二次的scrollViewWillBeginDragging 开始执行之后 ,上一次的 scrollViewDidEndDecelerating 执行问题
     因为经过验证发现,scrollViewWillBeginDragging 和 scrollViewDidEndDecelerating 并不是一对应的关系,
     就是我们快速滑动的时候,如果我们开始执行第二次的 scrollViewWillBeginDragging ,那么第一次 scrollViewDidEndDecelerating
     方法是会被跳过不执行的,所以我们不用担心 重复执行的问题
    */
    ///这里由于计算问题,会有误差,所以增减了0.5 的容错
    /*这里使用 self.bounds 和 scrollView.bounds是一样的,
    因为scrollView初始化的时候使用的frame 就是self.bounds
	  */
    if (scrollView.contentOffset.x > CGRectGetWidth(self.bounds) + 0.5) {
    
    
        if (self.currentIndex < count - 1) {
    
    
            self.currentIndex ++;
        } else {
    
    
            self.currentIndex = 0;
        }
        [self reloadAfterTranslation];
    } else if (scrollView.contentOffset.x < CGRectGetWidth(self.bounds) - 0.5) {
    
    
        if (self.currentIndex > 0) {
    
    
            self.currentIndex --;
        } else {
    
    
            self.currentIndex = count - 1;
        }
        [self reloadAfterTranslation];
    }
}

修复之后的效果图
请添加图片描述

demo

猜你喜欢

转载自blog.csdn.net/LIUXIAOXIAOBO/article/details/121534128
ios