PSCarouselView

分析需求

一般来说,我们在封装组件的时候,会先思考以下几点

  • 这个组件要做什么

  • 这个组件至少需要知道哪些信息

  • 这个组件会反馈哪些信息

这个阶段,我们还不会考虑组件的具体实现,仅仅对其做抽象。我们要做的东西不仅仅是适用于单个项目的,而应该是通用的,可以适应大部分同种类需求的。

Scene I

BA说,客户要在首页加个轮播。于是半天后设计师出了张图,看起来大概像这样:

-----1.jpg

我们按照上面的思路,拆分一下这个需求。

这个组件要做什么?

显而易见的:

  1. 展示多张图片

  2. 可以向左向右翻页

  3. PageControl的状态会根据图片的滚动而相应改变

隐含可能要做的:

  1. 支持左右两侧无限循环滚动

  2. 自动轮播

  3. 支持手动滑动

  4. 支持点击并进行相关的响应

  5. 图片的缓存

这个组件至少需要知道哪些信息?

一个封装得优秀的复杂度不高组件就像一个魔法盒子,只需要触发启动开关,就可以达到你期待的效果。极简的触发参数和条件是组件封装的精髓。在内容型App中,轮播图一般会用作推荐内容展示区域。在O2O类App中,轮播图一般会用作广告位。因此轮播区域图片的内容绝大多数都是动态的。在一般的C/S开发中,客户端要获取存储在服务器上的图片会获取它的URL,然后在需要的时候根据URL异步地加载这些图片。因此,我们找出了的轮播空间第一个必备条件:

一个图片URL地址数组。

1
@property (nonatomic, strong) NSArray *imageURLs; /**< 必须赋值。只要给这个imageURL赋值,会自动获取图片*/

这个时候我们已经可以根据数组内的URL,数组内URL的数量,完成轮播效果了。但还不够完善。试想,当数组为空的时候,我们的轮播控件是一个什么状态?网络比较慢,图片还在加载中的时候,我们的轮播控件是什么状态?就目前来说----空白一片。

每个App都有每个App的设计,但无论如何谁也不会容忍首页最醒目的部分出现一大片空白,因此占位图是必须的。我们告诉我们的控件,“没有图片的时候别傻愣着,显示这张图”。必备条件二:

占位图

1
@property (nonatomic, strong) UIImage *placeholder; /**< 没有轮播图时的占位图*/

有了以上信息我们的轮播控件已经可以在运行得比较好了。但是缺少了一定的定制性,能满足的需求面还不够广。比如说,让控件在需要自动轮播的地方自动轮播,在不需要自动轮播的地方保留无限滚动的特性,可以手动拨动?(之前有个产品提过这样的需求)比如说,这个控件是否应该提供可选的PageControl实现?依据设计师给的图不同,我们可能需要实现不同的PageControl,不管是颜色,布局,还是其可见隐藏都可能会有不同。这一部分复杂度不应该归到轮播控件中。但考虑到一些快速开发的需求,控件还是提供了一个默认选项。这些都是让控件变得更加可配置和灵活(同时也变得复杂)的可选信息。综上我们大概可以整理出以下属性:

1
2
@property (nonatomic,getter=isAutoMoving)      BOOL autoMoving; /**< 是否自动轮播,默认为NO*/
@property (nonatomic,getter=isShowPageControl) BOOL showPageControl; /**< 是否展示默认的PageControl,默认为YES*/

这个组件会反馈哪些信息?

上一点中,如果使用者需要自己实现PageControl,那么当前控件滚动到哪一页了,应该给出反馈。

不论在O2O的App中,还是资讯类App中,用户点击轮播必定会有相对应的响应,例如之乎日报点击跳转到对应的文章,淘宝点击查看大图等。因此用户点击的信息也必须反馈出来,以让控制器根据用户的操作进行不同的响应。

View层对Controller层的反馈一般有两种,一种是Target-Action,一种是Delegate。此处我们类似UITableView,给出一定的代理方法。遵循苹果的设计规范,让使用的开发者容易上手。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@protocol PSCarouselDelegate
@optional
/**
  *  告诉代理滚动到哪一页了
  *
  *  @param carousel self
  *  @param page     已经计算好,直接使用即可
  */
- (void)carousel:(PSCarouselView *)carousel didMoveToPage:(NSUInteger)page;
 
/**
  *   告诉代理用户点击了某一页
  *
  *  @param carousel
  *  @param index  imageURL的index  
  */
- (void)carousel:(PSCarouselView *)carousel didTouchPage:(NSUInteger)page;
@end

至此,轮播组件的架子已经明晰,剩下的就是如何实现,以及实现的时候需要考虑的一些细节。

实现过程

选择基类

苹果的UIKit提供了非常多优秀的类,可以作为我们轮播视图的基类。根据以上的分析,我们根据直觉,立马可以联想到以下三个类: UIPageViewController、UIScrollView、UICollectionView。

UIPageViewController提供了非常好的翻页封装,仅需要指定翻页的方向,和子ViewController的数组,就可以提供类似轮播的功能。并且UIPageViewController提供了供翻页的接口和必要的反馈信息,定义在UIPageViewControllerDelegate协议中。用UIPageViewController,我们只需要将每个轮播页封装成一个仅包含一个UIImageView的ViewController,并将其设为UIPageViewController的ViewControllers,并实现它的代理方法就很容易实现我们的轮播图。

UIScrollView提供了最基本的滚动封装。采用UIScrollView作为基类,需要自己根据图片的数量计算ContentSize,并在ScrollView相对应的代理方法中,根据Frame相关信息来计算页码,会比UIPageViewController稍微复杂。但好在,它是一个View。

UICollectionView做为UIScrollView的子类提供了比UIScrollView更好的封装,也提供了"翻页"的接口,并提供了一系列定位CollectionView的状态信息。相比UIScrollView,他提供了更深层的封装。同UIPageViewController一样,非常适合本作为本组件的基类。同时,当UICollectionView的一些代理方法不足以提供相关信息时,还可以通过UIScrollView的代理方法来解决。

采用UIPageViewController作为子类,考虑到使用者需要将其作为subViewController添加到它们的项目中,没有将一个View添加到ViewController中来得直观,综合考虑,PSCarouselView选择了UICollectionView作为其基类。

实现功能

如何利用UICollectionView在有限的图片数量下实现无限轮播?我们只需要N+2个Cell就可以实现无限轮播。如图:

QQ截图20151116151316.png

将imageURL数组中的URL,扩充为N+2。同时,将imageURLs的最后一个URL作为新数组的第一个URL,将imageURLs的第一个URL作为新数组的最后一个URL。然后在我们的CollectionView滚动到最后一个Cell时,跳转到第二个URL表示的IndexPath即可。自动轮播采用计时器来完成。在实现的时候,我们需要注意一下的几点

1.计时器的开启与暂停

自动轮播,通常我们会使用到计时器NSTimer。当我们在页面切换的过程中,需要注意计时器的开启与暂停,不然可能会出现一些不可预料的BUG。而一个ViewController的生命周期,View是不可能知道的。因此我们需要提供两个接口,供使用者开启/暂停计时器。

1
2
- (void)startMoving;
- (void)stopMoving;

另外,我们还需要注意App的生命周期,当App进入不活动的状态时,我们也需要将计时器暂停,并在回到活动状态时相应地启动。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#pragma mark - Notification
//程序被暂停的时候,应该停止计时器
- (void)applicationWillResignActive
{
     [self stopMoving];
}
 
//程序从暂停状态回归的时候,重新启动计时器
- (void)applicationDidBecomeActive
{
     if  (self.isAutoMoving)
     {
         [self startMoving];
     }
}

2.用户操作与自动轮播的冲突 

用户操作时如果轮播还是继续滚动,会导致用户产生不可控的错觉。《iOS Human Interface Guide》中强调过App需要给于用户控制感。因此,在用户手动"翻页"的时候,我们需要暂时暂停一下自动轮播,并在用户手动"翻页"完成后,重新进行轮播。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//用户手动拖拽,暂停一下自动轮播
- (void)scrollViewWillBeginDragging:(UIScrollView     *)scrollView
{
     [self removeTimer];
}
 
//用户拖拽完成,恢复自动轮播(如果需要的话)
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
     if  (self.isAutoMoving)
     {
         [self addTimer];
     }
}

3.图片的缓存与展示 

如何通过图片的URL来获得相对应的图片,并做好图片的缓存,以实现最大限度地节省流量?这个模块其实应该单独做一个有关图片缓存的库,而不应该包含到View层中来。本作采用了SDWebImage来实现这一功能。有兴趣的朋友可以尝试着实现一个图片缓存库。

以上,一个轮播组件的封装基本上完成了。更多实现上的细节请参看GitHub上的Demo

PSCarouselView.gif

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
智慧校园整体解决方案是响应国家教育信息化政策,结合教育改革和技术创新的产物。该方案以物联网、大数据、人工智能和移动互联技术为基础,旨在打造一个安全、高效、互动且环保的教育环境。方案强调从数字化校园向智慧校园的转变,通过自动数据采集、智能分析和按需服务,实现校园业务的智能化管理。 方案的总体设计原则包括应用至上、分层设计和互联互通,确保系统能够满足不同用户角色的需求,并实现数据和资源的整合与共享。框架设计涵盖了校园安全、管理、教学、环境等多个方面,构建了一个全面的校园应用生态系统。这包括智慧安全系统、校园身份识别、智能排课及选课系统、智慧学习系统、精品录播教室方案等,以支持个性化学习和教学评估。 建设内容突出了智慧安全和智慧管理的重要性。智慧安全管理通过分布式录播系统和紧急预案一键启动功能,增强校园安全预警和事件响应能力。智慧管理系统则利用物联网技术,实现人员和设备的智能管理,提高校园运营效率。 智慧教学部分,方案提供了智慧学习系统和精品录播教室方案,支持专业级学习硬件和智能化网络管理,促进个性化学习和教学资源的高效利用。同时,教学质量评估中心和资源应用平台的建设,旨在提升教学评估的科学性和教育资源的共享性。 智慧环境建设则侧重于基于物联网的设备管理,通过智慧教室管理系统实现教室环境的智能控制和能效管理,打造绿色、节能的校园环境。电子班牌和校园信息发布系统的建设,将作为智慧校园的核心和入口,提供教务、一卡通、图书馆等系统的集成信息。 总体而言,智慧校园整体解决方案通过集成先进技术,不仅提升了校园的信息化水平,而且优化了教学和管理流程,为学生、教师和家长提供了更加便捷、个性化的教育体验。
经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值