欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

iOS开发:无限循环轮播图

程序员文章站 2022-10-30 18:35:55
思路 (1)在第一张左边加一张最后一张的图片,往左滑到边缘结束后计算偏移量迅速定位成最后一张 #pragma mark - pagecontrol事件 // 这个是点击小圆点条进行切换,到边不...

思路

(1)在第一张左边加一张最后一张的图片,往左滑到边缘结束后计算偏移量迅速定位成最后一张
#pragma mark - pagecontrol事件
// 这个是点击小圆点条进行切换,到边不能循环
- (void)pagecontroltouched
{
    // 点击的时候停止计时
    [self.kvtimer setfiredate:[nsdate distantfuture]];
    
    // 滑到指定页面
    nsinteger curpageidx = _pagecontrol.currentpage;
    cgfloat offsetx = self.frame.size.width * (curpageidx + 1);
    [self.scrollview setcontentoffset:cgpointmake(offsetx, 0) animated:yes];

    // 重新开启定时器
    [self.kvtimer setfiredate:[nsdate datewithtimeinterval:ktimerinterval sincedate:[nsdate date]]];
}

#pragma mark - 滚动事件
- (void)scrollviewwillbegindragging:(uiscrollview *)scrollview
{
//    printf("start drag\n");
    // 记录偏移量
    preoffsetx = scrollview.contentoffset.x;
    // 开始手动滑动时暂停定时器
    [self.kvtimer setfiredate:[nsdate distantfuture]];
}

- (void)scrollviewdidenddecelerating:(uiscrollview *)scrollview
{
//    printf("end drag\n");
    // 左右边界
    cgfloat leftedgeoffsetx = 0;
    cgfloat rightedgeoffsetx = self.frame.size.width * (_pagecount + 1);
    
    if (scrollview.contentoffset.x < preoffsetx)
    {
        // 左滑
        if (scrollview.contentoffset.x > leftedgeoffsetx)
        {
            self.pagecontrol.currentpage = scrollview.contentoffset.x / self.frame.size.width - 1;
        }
        else if (scrollview.contentoffset.x == leftedgeoffsetx)
        {
            self.pagecontrol.currentpage = _pagecount - 1;
        }
        
        if (scrollview.contentoffset.x == leftedgeoffsetx)
        {
            self.scrollview.contentoffset = cgpointmake(self.frame.size.width * _pagecount, 0);
        }
    }
    else
    {
        // 右滑
        
        // 设置小点
        if (scrollview.contentoffset.x < rightedgeoffsetx)
        {
            self.pagecontrol.currentpage = scrollview.contentoffset.x / self.frame.size.width - 1;
        }
        else if (scrollview.contentoffset.x == rightedgeoffsetx)
        {
            self.pagecontrol.currentpage = 0;
        }
        
        // 滑动完了之后从最后多余页赶紧切换到第一页
        if (scrollview.contentoffset.x == rightedgeoffsetx)
        {
            self.scrollview.contentoffset = cgpointmake(self.frame.size.width, 0);
        }

    }
    // 结束后又开启定时器
    [self.kvtimer setfiredate:[nsdate datewithtimeinterval:ktimerinterval sincedate:[nsdate date]]];
}

- (void)scrollviewdidendscrollinganimation:(uiscrollview *)scrollview
{
//    printf("end scroll\n");
}

#pragma mark - 定时器控制的滑动
// 往右边滑
- (void)changepageright
{
    // 设置当前需要偏移的量,每次递增一个page宽度
    cgfloat offsetx = _scrollview.contentoffset.x + cgrectgetwidth(self.frame);
    
    // 根据情况进行偏移
    cgfloat edgeoffsetx = self.frame.size.width * (_pagecount + 1);  // 最后一个多余页面右边缘偏移量
    
    // 从多余页往右边滑,赶紧先设置为第一页的位置
    if (offsetx > edgeoffsetx)
    {
        // 偏移量,不带动画,欺骗视觉
        self.scrollview.contentoffset = cgpointmake(self.frame.size.width, 0);
        // 这里提前改变下一个要滑动到的位置为第二页
        offsetx = self.frame.size.width * 2;
    }
    
    // 带动画滑动到下一页面
    [self.scrollview setcontentoffset:cgpointmake(offsetx, 0) animated:yes];
    if (offsetx < edgeoffsetx)
    {
        self.pagecontrol.currentpage = offsetx / self.frame.size.width - 1;
    }
    else if (offsetx == edgeoffsetx)
    {
        // 最后的多余那一页滑过去之后设置小点为第一个
        self.pagecontrol.currentpage = 0;
    }
}

// 往左边滑
- (void)changepageleft
{
    // 设置当前需要偏移的量,每次递减一个page宽度
    cgfloat offsetx = _scrollview.contentoffset.x - cgrectgetwidth(self.frame);
    
    // 根据情况进行偏移
    cgfloat edgeoffsetx = 0;  // 最后一个多余页面左边缘偏移量
    
    // 从多余页往左边滑动,先设置为最后一页
    if (offsetx < edgeoffsetx)
    {
        self.scrollview.contentoffset = cgpointmake(self.frame.size.width * _pagecount, 0);
        offsetx = self.frame.size.width * (_pagecount - 1);
    }
    
    // 带动画滑动到前一页面
    [self.scrollview setcontentoffset:cgpointmake(offsetx, 0) animated:yes];
    if (offsetx > edgeoffsetx)
    {
        self.pagecontrol.currentpage = offsetx / self.frame.size.width - 1;
    }
    else if (offsetx == edgeoffsetx)
    {
        // 最后的多余那一页滑过去之后设置小点为最后一个
        self.pagecontrol.currentpage = _pagecount - 1;
    }
}

 

(2)总共只有左、中、右三个页面,每次滑动后重新进行数据跟页面的关联

#pragma mark - 定时器回调
- (void)changepageright
{
    // 往右滑并且设置小圆点,永远都是滑到第三页
    [_scrollview setcontentoffset:cgpointmake(self.frame.size.width * 2, 0) animated:yes];
    [self resetpageindex:yes];
}

- (void)changepageleft
{
    // 往左滑,永远都是滑动到第一页
    [_scrollview setcontentoffset:cgpointmake(0, 0) animated:yes];
    [self resetpageindex:no];
}

#pragma mark - 重新设置索引和页面图片
- (void)resetpageindex:(bool)isright
{
    if (isright)
    {
        // 根据之前的page下标来修改
        if (_prepageindex == _pagecount - 1)
        {
            // 到头了就回到第一个
            _pagecontrol.currentpage = 0;
        }
        else
        {
            // 这里用_prepageindex来算,否则点击小圆点条会重复计算了
            _pagecontrol.currentpage = _prepageindex + 1;
        }
    }
    else
    {
        if (_prepageindex == 0)
        {
            _pagecontrol.currentpage = _pagecount - 1;
        }
        else
        {
            _pagecontrol.currentpage = _prepageindex - 1;
        }
    }
    _prepageindex = _pagecontrol.currentpage;
}

- (void)resetpageview
{
    // 每次滑动完了之后又重新设置当前显示的page时中间的page
    uiimageview *leftpage = [_scrollview viewwithtag:1000];
    uiimageview *middlepage = [_scrollview viewwithtag:1001];
    uiimageview *rightpage = [_scrollview viewwithtag:1002];
    
    if (_pagecontrol.currentpage == _pagecount - 1)
    {
        // n- 1 -> n -> 0
        leftpage.image = _kvimagearray[_pagecontrol.currentpage - 1];
        middlepage.image = _kvimagearray[_pagecontrol.currentpage];
        rightpage.image = _kvimagearray.firstobject;
        
    }
    else if (_pagecontrol.currentpage == 0)
    {
        // n -> 0 -> 1
        // 到尾部了,改成从头开始
        leftpage.image = _kvimagearray.lastobject;
        middlepage.image = _kvimagearray.firstobject;
        rightpage.image = _kvimagearray[1];
    }
    else
    {
        // x - 1 -> x -> x + 1
        leftpage.image = _kvimagearray[_pagecontrol.currentpage - 1];
        middlepage.image = _kvimagearray[_pagecontrol.currentpage];
        rightpage.image = _kvimagearray[_pagecontrol.currentpage + 1];
    }
    
    // 重新设置偏移量
    _scrollview.contentoffset = cgpointmake(self.frame.size.width, 0);
}

#pragma mark - pagecontrol事件
- (void)pagecontroltouched
{
    [self stoptimer];
    
    nsinteger curpageindex = _pagecontrol.currentpage;
    if (curpageindex > _prepageindex)
    {
        // 右滑
        [self changepageright];
    }
    else
    {
        // 左滑
        [self changepageleft];
    }
    
    [self starttimer];
}

#pragma mark - scrollview滑动代理
- (void)scrollviewwillbegindragging:(uiscrollview *)scrollview
{
    // 先停掉定时器
    [self stoptimer];
    
}

- (void)scrollviewdidenddecelerating:(uiscrollview *)scrollview
{
    // 手动拖拽滑动结束后
    if (scrollview.contentoffset.x > self.frame.size.width)
    {
        // 右滑
        [self resetpageindex:yes];
    }
    else
    {
        // 左滑
        [self resetpageindex:no];
    }
    [self resetpageview];
    
    // 开启定时器
    [self starttimer];
}

- (void)scrollviewdidendscrollinganimation:(uiscrollview *)scrollview
{
    // 自动滑动结束后重新设置图片
    [self resetpageview];
}

 

源代码下载

github:轮播图