一款健壮性良好,高度可扩展的iOS水平轮播组件 LBHorizontalLoopView,使用三个视图完成轮播逻辑,内部使用了重用,支持同时展示不同样式轮播内容,支持快速拖动,支持pod导入

首先看效果图
请添加图片描述


本框架使用三个视图实现轮播效果原理

底部有一个s c rolllview , scrollview的内容宽度为3 * 视图宽度
首次展示第一个展示在中间,左边展示最后一个,右边展示第二个
,当向右拖动一次之后,迅速将scrollView的偏移量
恢复到中间,并且当前索引增加一,并根据当前索引刷新三个子视图
,这样就达到了轮播的效果,并且该框架支持多种内容视图同时展示,
扩展性更好

核心代码

///这里是结束滚动之后需要将改变当前索引,并恢复偏移量,并刷新数据
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
    NSInteger count = self.numberOfLoopView;
    NSInteger index = scrollView.contentOffset.x / CGRectGetWidth(self.bounds);
    if (index == 2) {
        if (self.currentIndex < count - 1) {
            self.currentIndex ++;
        } else {
            self.currentIndex = 0;
        }
    } else if (index == 0) {
        if (self.currentIndex > 0) {
            self.currentIndex --;
        } else {
            self.currentIndex = count - 1;
        }
    }
    [self reloadAfterTranslation];
    if (self.delegate &&
        [self.delegate respondsToSelector:@selector(loopView:didScrollToCellAtIndex:)]) {
        [self.delegate loopView:self didScrollToCellAtIndex:self.currentIndex];
    }
    self.isDragging = NO;
}

///这里是为了修复快速拖动导致的不能滚动的问题
- (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
     方法是会被跳过不执行的,所以我们不用担心 重复执行的问题
    */
    if (scrollView.contentOffset.x > CGRectGetWidth(scrollView.bounds)) {
        if (self.currentIndex < count - 1) {
            self.currentIndex ++;
        } else {
            self.currentIndex = 0;
        }
        [self reloadAfterTranslation];
    } else if (scrollView.contentOffset.x < CGRectGetWidth(scrollView.bounds)) {
        if (self.currentIndex > 0) {
            self.currentIndex --;
        } else {
            self.currentIndex = count - 1;
        }
        [self reloadAfterTranslation];
    }
}

///恢复偏移量,刷新数据
- (void)reloadAfterTranslation
{
      ///注意,这里需要先刷新中间视图,再恢复偏移量,为了实现无缝过渡的效果
    [self reloadMiddleCell];
    self.contentScrollView.contentOffset = CGPointMake(CGRectGetWidth(self.bounds), 0);
//    [self.contentScrollView setContentOffset:CGPointMake(CGRectGetWidth(self.bounds), 0) animated:NO];
    ///回复偏移量之后,刷新左右两边的cell
    [self reloadLeftCell];
    [self reloadRightCell];
}

以上就是该框架的和新代码,已验证该框架的健壮性良好,
扩展性较强,可以满足大多数轮播需求

如:可以在不同的索引下展示不同的视图

- (LBHorizontalLoopViewCell *)cellForIndex:(NSInteger)index inLoopView:(LBHorizontalLoopView *)loopView
{
    if (index % 2 == 0) {
        LBCell *cell = [loopView dequeueReusableCellWithIdentifier:NSStringFromClass([LBCell class])];
        NSString  *content = self.dataArray[index];
        [cell updateWithModel:content];
        return cell;
    }
    LBBannerCell *cell = [loopView dequeueReusableCellWithIdentifier:NSStringFromClass([LBBannerCell class])];
    return cell;
}

demo

使用方法
pod ‘LBHorizontalLoopView’

自定义轮播视图继承于 LBHorizontalLoopViewCell

@interface LBBannerCell : LBHorizontalLoopViewCell

@end

创建 轮播视图,并设置代理对象和数据源对象,注册自定义cell

- (LBHorizontalLoopView *)loopView
{
    if (!_loopView) {
        _loopView = [[LBHorizontalLoopView alloc] initWithFrame:CGRectMake(0, 100, CGRectGetWidth(self.view.bounds), 150)];
        [_loopView registerClass:[LBCell class] forViewReuseIdentifier:NSStringFromClass([LBCell class])];
        [_loopView registerClass:[LBBannerCell class] forViewReuseIdentifier:NSStringFromClass([LBBannerCell class])];
        _loopView.dataSource = self;
        _loopView.delegate = self;
    }
    return _loopView;
}

实现协议方法

#pragma mark - LBHorizontalLoopViewDelegate, LBHorizontalLoopViewDataSource
- (NSInteger)viewNumberOfLoopView:(LBHorizontalLoopView *)loopView
{
    return self.dataArray.count;
}

- (LBHorizontalLoopViewCell *)cellForIndex:(NSInteger)index inLoopView:(LBHorizontalLoopView *)loopView
{
    if (index % 2 == 0) {
        LBCell *cell = [loopView dequeueReusableCellWithIdentifier:NSStringFromClass([LBCell class])];
        NSString  *content = self.dataArray[index];
        [cell updateWithModel:content];
        return cell;
    }
    LBBannerCell *cell = [loopView dequeueReusableCellWithIdentifier:NSStringFromClass([LBBannerCell class])];
    return cell;
}

- (void)loopView:(LBHorizontalLoopView *)loopView didClickCellAtIndex:(NSInteger)index
{
}

- (void)loopView:(LBHorizontalLoopView *)loopView didScroll:(UIScrollView *)scrollView
{
    
}

- (void)loopView:(LBHorizontalLoopView *)loopView didScrollToCellAtIndex:(NSInteger)index
{
    
}

开始轮播
[self.loopView reloadDataAndStartRoll];


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
LoopView 是一个强大的轮转大图控件,并且提供了许多配置方法来达到您的显示效果和需求。github地址:https://github.com/xuehuayous/Android-LoopView介绍博客地址:http://blog.csdn.net/xuehuayous/article/details/50518393在项目中使用 LoopView如果您的项目使用 Gradle 构建, 只需要在您的build.gradle文件添加下面一行到 dependencies :    compile 'com.kevin:loopview:1.0.5'简单使用在layout.xml 中配置LoopView在Layout文件添加<com.kevin.loopview.AdLoopView<com.kevin.loopview.AdLoopView     android:id="@ id/main_act_adloopview"     android:layout_width="match_parent"     android:layout_height="192dp"> </com.kevin.loopview.AdLoopView>在代码中配置AdLoopView mLoopView = (AdLoopView) this.findViewById(R.id.main_act_adloopview); String json = LocalFileUtils.getStringFormAsset(this, "loopview_date.json"); // 使用 JsonTool 封装 JSON 数据到实体对象 LoopData loopData = JsonTool.toBean(json, LoopData.class); // 通过对象的方式设置数据 mLoopView.refreshData(loopData); // 开始轮转 mLoopView.startAutoLoop(); // 设置点击监听 mLoopView.setOnClickListener(new BaseLoopAdapter.OnItemClickListener() {         @Override         public void onItemClick(PagerAdapter parent, View view,              int position, int realPosition) {             // 获取数据             LoopData loopData = mLoopView.getLoopData();             String url = loopData.items.get(position).link;             // 通过系统浏览器打开跳转链接             Intent intent = new Intent();             intent.setData(Uri.parse(url));             intent.setAction(Intent.ACTION_VIEW);             startActivity(intent);         }     });更多配置XML 配置在XML中使用AdLoopView,可以有如下配置:<com.kevin.loopview.AdLoopView     android:id="@ id/adloop_act_adloopview"     android:layout_width="match_parent"     android:layout_height="192dp"     kevin:loop_interval="5000"     kevin:loop_dotMargin="5dp"     kevin:loop_autoLoop="[true|false]"     kevin:loop_dotSelector="@drawable/ad_dots_selector"     kevin:loop_layoutId="@layout/ad_loopview_layout"> </com.kevin.loopview.AdLoopView>在代码中配置// 设置ViewPager页面切换时间 mLoopView.setScrollDuration(1000); // 设置轮转时间间隔 mLoopView.setInterval(3000); // 以集合的方式初始化数据 mLoopView.setLoopViewPager(List<Map<String, String>> data); // 以JSON的方式初始化数据 mLoopView.setLoopViewPager(String jsonData); // 以数据实体的方式初始化数据 mLoopView.setLoopViewPager(LoopData rotateData); // 以集合的方式刷新数据 mLoopView.refreshData(final List<Map<String, String>> data); // 以数据实体的方式刷新数据 mLoopView.refreshData(LoopData loopData); // 以JSON的方式刷新数据 mLoopView.refreshData(String jsonData); // 获取配置的轮转大图数据 mLoopView.getLoopData(); // 开始自动轮转 mLoopView.startAutoLoop(); // 在指定时间延迟后自动轮转 mLoopView.startAutoLoop(long delayTimeInMills); // 停止自动轮转 mLoopView.stopAutoLoop(); // 设置自定义布局 mLoopView.setLoopLayout(int layoutResId);

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值