Swift编程(五):学做一个属于自己的View

写在前面:

欢迎大家关注我的个人博客:博客地址,这里主要是我在个人开发时候遇到的坑和挖完的坑,包括 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
```

你可能感兴趣的:(Swift编程(五):学做一个属于自己的View)