写在前面:
欢迎大家关注我的个人博客:博客地址,这里主要是我在个人开发时候遇到的坑和挖完的坑,包括 PHP CentOS 以及 Swift 等相关只是
今天教给大家如何创建一个属于自己的View。(MVC设计模式有感)
上次的总结对我影响很大,让我对IOS的MVC设计理解的更入更深了、也更清晰了。
我觉得平时养成总结的习惯,应该算是一个程序员的自我修养了
目标:
- 学习如何做一个属于自己的公共View(ImageScroller)
- 学习如何在视图类中创建代理,以及调用是使用代理
- 学会像使用UITableView那样使用我们自己的View
- 记录一点Swift下如何使用定时器 和 简单的小动画
效果图
scroller.gif
具体步骤:
每一个方法我都做了备注,以便大家理解
1. 创建View:ImageScroller: UIView
```swift
class ImageScroller: UIView {weak var delegate: ImageScrollerDelegate? //属性参数 var imageViewArray = Array
() var scroller: UIScrollView! var pageControl:UIPageControl! //图片数 private var imageCount:Int = 0 //初始化 override init(frame: CGRect) { super.init(frame: frame) self.backgroundColor = UIColor.blueColor() self.frame = frame } //重载数据的方法 func reload() { if let delegate = self.delegate { self.imageCount = delegate.numberOfImageViewsForImageScroller(self) initializeScrollView(self.imageCount) for var i = 0; i < self.imageCount; i++ { let imageView = delegate.imageScrollerAtIndex(self, index: i) imageView.frame = self.scroller.bounds var frame = imageView.frame frame.origin.x = CGFloat(i) * self.frame.size.width imageView.frame = frame self.scroller.addSubview(imageView) } initializePageControl() autoScroll() } } //组件一:UIScrollView的初始化 func initializeScrollView(count: Int){ self.scroller = UIScrollView() self.scroller.delegate = self self.scroller.contentSize = CGSizeMake(CGFloat(count) * self.frame.width,0) self.scroller.backgroundColor = UIColor.whiteColor() self.scroller.frame = self.bounds self.scroller.pagingEnabled = true self.scroller.bounces = false //反弹效果 self.scroller.showsHorizontalScrollIndicator = false let tapRecognizer = UITapGestureRecognizer(target: self, action:Selector("scrollerTapped:")) self.scroller.addGestureRecognizer(tapRecognizer) self.addSubview(self.scroller) } //组件二:UIPageControl的初始化 func initializePageControl(){ // pageControl: 图片下面的圆点 self.pageControl = UIPageControl() self.pageControl.center = CGPointMake(self.scroller.frame.width/2, self.scroller.frame.height-30) self.pageControl.currentPageIndicatorTintColor = UIColor.redColor() self.pageControl.pageIndicatorTintColor = UIColor.grayColor() self.pageControl.numberOfPages = self.imageCount self.addSubview(pageControl) } //自动滚动方法 func autoScroll(){ let timer = NSTimer(timeInterval: 4, target: self, selector: "scrolling", userInfo: nil, repeats: true) NSRunLoop.currentRunLoop().addTimer(timer, forMode: NSDefaultRunLoopMode) } //滚动效果设计(这里设计的比较简单) func scrolling(){ var index = Int(self.scroller.contentOffset.x / self.frame.size.width) if index >= self.imageCount - 1 { index = 0 UIView.animateWithDuration(1) { () -> Void in self.scroller.contentOffset.x = 0 self.pageControl.currentPage = index } }else{ UIView.animateWithDuration(0.5) { () -> Void in self.scroller.contentOffset.x = self.frame.width * (CGFloat(index) + 1) self.pageControl.currentPage = index + 1 } } } //点击事件 func scrollerTapped(gesture: UITapGestureRecognizer) { if let delegate = self.delegate { let index = Int(self.scroller.contentOffset.x / self.frame.size.width) delegate.imageScrollerClickedAtIndex(self, index: index) self.pageControl.currentPage = index } } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } }
//UIScrollView的拓展扩展:UIPageControl与图片联动
extension ImageScroller: UIScrollViewDelegate {
func scrollViewDidEndDecelerating(scrollView: UIScrollView) {
let index = Int(self.scroller.contentOffset.x / self.frame.size.width)
self.pageControl.currentPage = index
}
}### 2.创建自己View的代理(Delegate) >把代理卸载 最上面。 其实代理是个很方便的东西,我这里写了三个,我们知道UITableView有两种:Delegate(代理)和 DataSource(数据源),在上一节我说过DataSource是一种特殊的代理,其实他本质就是代理,只不过如果代理过多,需要帮代理分一下类,那么跟数据相关的例如:多少条数据,每条数据的cell等等都归类与名字叫DataSource下面了,就这么简单!
```swift //属性代理 @objc protocol ImageScrollerDelegate { //获取所有的图片数 func numberOfImageViewsForImageScroller(scroller: ImageScroller) -> Int //获取每个UIImageView func imageScrollerAtIndex(scroller: ImageScroller, index: Int) -> UIImageView //每一个图片的点击事件 func imageScrollerClickedAtIndex(scroller: ImageScroller, index: Int) } ```> 我们这里只有三个店里所以我就不需要明确分类了 在上面的类中我已经没明确使用到了上面三个代理,不知道大家看代码的时候有没有发现,下面我一一介绍一下,每个代理的作用。 ##注意: 如果我在我的代理方法前面加一个 optional 那么就说明在使用我们的View时,此方法没有必要使用。我这里三个方法都是必须要被代理的,否则会报错 ### 3.代理的使用 >//这个必须写上,以便调用我们为View写好的代理 weak var delegate: ImageScrollerDelegate?```swift //重载数据的方法 func reload() { if let delegate = self.delegate { self.imageCount = delegate.numberOfImageViewsForImageScroller(self) initializeScrollView(self.imageCount) for var i = 0; i < self.imageCount; i++ { let imageView = delegate.imageScrollerAtIndex(self, index: i) imageView.frame = self.scroller.bounds var frame = imageView.frame frame.origin.x = CGFloat(i) * self.frame.size.width imageView.frame = frame self.scroller.addSubview(imageView) } initializePageControl() autoScroll() } } ```> 我在重载数据是使用了次代理,使用方法很简单,只需要在我们需要他的使用,通过delegate.numberOfImageViewsForImageScroller(self)
的形式调用即可,(注意)代理是给那些实例我们View的Controller使用的,我们要相信他们会把我们需要的图片数imageCount通过delegate.numberOfImageViewsForImageScroller(self)
传过来的,其实代理不过是个中间变量。 总结: - 需求(一):图片数(Int) - 代理方法: func numberOfImageViewsForImageScroller(scroller: ImageScroller) -> Int - 使用: self.imageCount = delegate.numberOfImageViewsForImageScroller(self) > - 需求(二):需要具体的图片(UIImageView) 代理方法: func imageScrollerAtIndex(scroller: ImageScroller, index: Int) -> UIImageView 使用: let imageView = delegate.imageScrollerAtIndex(self, index: i) > - 需求(三):点击事件(Void) 代理方法: func imageScrollerClickedAtIndex(scroller: ImageScroller, index: Int) 使用:```swift //点击事件 func scrollerTapped(gesture: UITapGestureRecognizer) { if let delegate = self.delegate { let index = Int(self.scroller.contentOffset.x / self.frame.size.width) delegate.imageScrollerClickedAtIndex(self, index: index) self.pageControl.currentPage = index } } ```### 4.在Controller中使用ImageScroller > 1)实例并初始化ImageScroller```swift //尺寸 imageScroller = ImageScroller(frame: CGRectMake(0, 0, self.view.frame.width, 300)) imageScroller.delegate = self self.view.addSubview(imageScroller) imageScroller.reload() ```> 2)添加代理```swift extension MainViewController: ImageScrollerDelegate { func numberOfImageViewsForImageScroller(scroller: ImageScroller) -> Int { return 4 //测试阶段模拟数据 } func imageScrollerAtIndex(scroller: ImageScroller, index: Int) -> UIImageView { let image = UIImage(named: "Welcome\\\\\\\\(1 + index).jpg") let imageView = UIImageView() imageView.image = image imageView.backgroundColor = UIColor.blackColor() //ScaleAspectFill:不影响图片的尺寸,只显示一部分 //ScaleAspectFit:不影响图片的尺寸,按比例缩小全图显示 //ScaleToFill:拉伸图片比例去适应全屏 imageView.contentMode = .ScaleAspectFill return imageView } func imageScrollerClickedAtIndex(scroller: ImageScroller, index: Int) { print(index) } } ```## 总结小知识: ###1. IOS定时器: >方法一```swift let timer = NSTimer(timeInterval: 4, target: self, selector: "scrolling", userInfo: nil, repeats: true) NSRunLoop.currentRunLoop().addTimer(timer, forMode: NSDefaultRunLoopMode) ```###2. 几种常用的contentMode方式```swift //ScaleAspectFill:不影响图片的尺寸,只显示一部分 //ScaleAspectFit:不影响图片的尺寸,按比例缩小全图显示 //ScaleToFill:拉伸图片比例去适应全屏 imageView.contentMode = .ScaleAspectFill ```