写在前面:
欢迎大家关注我的个人博客:<a href="http://blog.noasis.cn" >博客地址</a>,这里主要是我在个人开发时候遇到的坑和挖完的坑,包括 PHP CentOS 以及 Swift 等相关只是
今天教给大家如何创建一个属于自己的View。(MVC设计模式有感)
上次的总结对我影响很大,让我对IOS的MVC设计理解的更入更深了、也更清晰了。
我觉得平时养成总结的习惯,应该算是一个程序员的自我修养了
目标:
- 学习如何做一个属于自己的公共View(ImageScroller)
- 学习如何在视图类中创建代理,以及调用是使用代理
- 学会像使用UITableView那样使用我们自己的View
- 记录一点Swift下如何使用定时器 和 简单的小动画
效果图
scroller.gif具体步骤:
每一个方法我都做了备注,以便大家理解
1. 创建View:ImageScroller: UIView
<pre>```swift
class ImageScroller: UIView {
weak var delegate: ImageScrollerDelegate?
//属性参数
var imageViewArray = Array<UIImage>()
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下面了,就这么简单!
<pre>```swift
//属性代理
@objc protocol ImageScrollerDelegate {
//获取所有的图片数
func numberOfImageViewsForImageScroller(scroller: ImageScroller) -> Int
//获取每个UIImageView
func imageScrollerAtIndex(scroller: ImageScroller, index: Int) -> UIImageView
//每一个图片的点击事件
func imageScrollerClickedAtIndex(scroller: ImageScroller, index: Int)
}
```</pre>
> 我们这里只有三个店里所以我就不需要明确分类了
在上面的类中我已经没明确使用到了上面三个代理,不知道大家看代码的时候有没有发现,下面我一一介绍一下,每个代理的作用。
##注意:
如果我在我的代理方法前面加一个 optional 那么就说明在使用我们的View时,此方法没有必要使用。我这里三个方法都是必须要被代理的,否则会报错
### 3.代理的使用
>//这个必须写上,以便调用我们为View写好的代理
weak var delegate: ImageScrollerDelegate?
<pre>```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()
}
}
```</pre>
> 我在重载数据是使用了次代理,使用方法很简单,只需要在我们需要他的使用,通过 <code>delegate.numberOfImageViewsForImageScroller(self)</code>的形式调用即可,(注意)代理是给那些实例我们View的Controller使用的,我们要相信他们会把我们需要的图片数imageCount通过<code>delegate.numberOfImageViewsForImageScroller(self)</code>传过来的,其实代理不过是个中间变量。
总结:
- 需求(一):图片数(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)
使用:
<pre>```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
}
}
```</pre>
### 4.在Controller中使用ImageScroller
> 1)实例并初始化ImageScroller
<pre>```swift
//尺寸
imageScroller = ImageScroller(frame: CGRectMake(0, 0, self.view.frame.width, 300))
imageScroller.delegate = self
self.view.addSubview(imageScroller)
imageScroller.reload()
```</pre>
> 2)添加代理
<pre>```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)
}
}
```</pre>
## 总结小知识:
###1. IOS定时器:
>方法一
<pre>```swift
let timer = NSTimer(timeInterval: 4, target: self, selector: "scrolling", userInfo: nil, repeats: true)
NSRunLoop.currentRunLoop().addTimer(timer, forMode: NSDefaultRunLoopMode)
```</pre>
###2. 几种常用的contentMode方式
<pre>```swift
//ScaleAspectFill:不影响图片的尺寸,只显示一部分
//ScaleAspectFit:不影响图片的尺寸,按比例缩小全图显示
//ScaleToFill:拉伸图片比例去适应全屏
imageView.contentMode = .ScaleAspectFill
```</pre>
网友评论