swift:UIKit中Demo(二)

这一节,继续为大家提供一个Demo,用来说明Swift中的各种语法及在UIView中的基本使用。效果图如下:

看起来,这个Demo非常的简单。但是为了进行详细的语法说明,它的实现,均是用代码实现的,并且下方的进度条都是"组装"起来的。

结构分析:

1. 有一个根控制器ViewController.swift, 它只是用来展示上面显示的文字(秋恨雪)。

2. 然后下面的文字大小切换及进度条这个整体是一个自定义的View(LFFontView.swift)

3. 进度条部分又有三部分内容组成:(底部的灰色的总进度View,进度条上面的滑块View,实时显示进度的红色的View)。

大致的结构图如下:

1. 初始化相关的属性

lazy private var buttons: [UIButton] = [UIButton]()

private var selectedButton: UIButton?

lazy private var bottomLine = UIImageView(image: UIImage(named: "正文字号-滑条"))
lazy private var topLine = UIImageView(image: UIImage(named: "正文字号-滑条红"))
lazy private var slider = UIImageView(image: UIImage(named: "正文字号-滑块"))

1) 数组buttons用来存放 "Aa" 这四个按钮。

2) 属性selectedButton 用来存放当前选中了哪一个"Aa"。

3) 三个ImageView就是上面3D图中的前三个内容,即他们组成滑动条。

2. 初始化相关的View

convenience init() {
   self.init(frame: CGRectZero)
}

override init(frame: CGRect) {
    super.init(frame: frame) // init(frame: CGRect)是UIView的默认构造方法
    self.frame = CGRectMake(0, kFontViewY, UIScreen.mainScreen().bounds.width, kFontViewH)
    initDetailViews()
}

1)  便利的无参构造方法调用了直接的有参构造方法,并且进行View的frame的设置。

2)  initDetailViews方法进行具体的子View的初始化工作。

3. 具体子View的设置及事件处理

func initDetailViews() {

        // Init Buttons
        createButton(normal: "正文字号-小(默认)", selected: "正文字号-小", itemStyle: .Small)
        createButton(normal: "正文字号-中(默认)", selected: "正文字号-中", itemStyle: .Middle)
        createButton(normal: "正文字号-大(默认)", selected: "正文字号-大", itemStyle: .Big)
        createButton(normal: "正文字号-大+(默认)", selected: "正文字号-大+", itemStyle: .SuperBig)

        // Init Others
        addSubview(bottomLine)
        addSubview(topLine)
        addSubview(slider)
    }

    func createButton(#normal: String, selected: String, itemStyle: LFFontViewItemStyle) {
        let fontBtn = UIButton()
        fontBtn.adjustsImageWhenHighlighted = false
        fontBtn.tag =  itemStyle.rawValue
        fontBtn.setImage(UIImage(named: normal), forState: UIControlState.Normal)
        fontBtn.setImage(UIImage(named: selected), forState: UIControlState.Selected)
        fontBtn.addTarget(self, action: "buttonClick:", forControlEvents: UIControlEvents.TouchDown)
        fontBtn.imageView?.contentMode = UIViewContentMode.ScaleAspectFit

        fontBtn.backgroundColor = UIColor.grayColor()
        buttons.append(fontBtn)
        addSubview(fontBtn)
    }

    func buttonClick(sender: UIButton) {
        selectedButton?.selected = false
        sender.selected = true
        selectedButton = sender

        setNeedsLayout()
    }

    override func layoutSubviews() {

        super.layoutSubviews()

        let btnY: CGFloat = 0
        let btnW = frame.size.width / 4
        let btnH: CGFloat = 68

        let count = buttons.count
        for i in 0..<count {
            var btn = buttons[i]
            var btnX = CGFloat(i) * btnW
            btn.frame = CGRectMake(btnX, btnY, btnW, btnH)
        }

        // self.bottomLine
        let bottomLineX: CGFloat = btnW * 0.5
        let bottomLineY: CGFloat = 80
        let bottomLineW: CGFloat = frame.size.width - btnW
        let bottomLineH: CGFloat = 3
        bottomLine.frame = CGRectMake(bottomLineX, bottomLineY, bottomLineW, bottomLineH)

        // self.slider
        let sliderCenterX = selectedButton == nil ? bottomLineX : selectedButton?.center.x;

        slider.center.x = sliderCenterX!
        slider.center.y = bottomLine.center.y

        // self.topLine
        topLine.frame = bottomLine.frame;
        topLine.frame.size.width = sliderCenterX! - bottomLineX
    }

代码中使用到了常量及枚举,他们的定义如下:

let kFontViewH: CGFloat = 100
let kFontViewY: CGFloat = UIScreen.mainScreen().bounds.height - kFontViewH

enum LFFontViewItemStyle : Int {
    case Small
    case Middle
    case Big
    case SuperBig
}

这些代码书写完毕后,效果就像文章开头贴出的效果,只是点击按钮切换的时候,文字大小不会发生改变。在解决这个问题之前,我先对上面所涉及到的知识点进行归纳总结。

1) Swift中没有了宏的概念,所以定义常量,我们可以直接使用let关键字,如上面的kFontViewH 常量。

2) Swift中枚举的定义与objective-c有了很大的不同,如上面的LFFontViewItemStyle 枚举成员直接都用case标识,并且在使用枚举的时候,有两种写法:

LFFontViewItemStyle.Small 或者 .Small。

3) 代码中使用到的成员或者属性等最好使用let修饰符,除非这些成员或者属性需要进行赋值变化等操作。例如:在layoutSubviews方法中,很多的成员都是用了let修饰符,而在属性定义的地方,很多都使用的var修饰符,因为它们要么是需要动态计算或者有赋值等操作,要么涉及到懒加载操作。

4) 在objective-c中,对属性的调用,我们一般使用“self.属性” 的写法。在Swift中可以直接使用属性名称进行操作,也就是“self.”可以省略。例如:addSubview(bottomLine), buttons.append(fontBtn), selectedButton?.selected 等。 但有一些self的地方是不可以省略的,例如:

<span style="font-family:SimSun;font-size:18px;">self.frame = CGRectMake(0, kFontViewY, UIScreen.mainScreen().bounds.width, kFontViewH)</span>

如果这里直接写frame的话,会和init(frame:
CGRect) 中的frame产生歧义。

5) 文章中还出现了很多的 "?" 及 "!" 的使用,如果有什么不清楚的,请参考
《Swift:可选类型(Optional) 》

6) 文章中涉及到了方法形参的修饰符问题,例如:

<span style="font-family:SimSun;font-size:18px;">func createButton(#normal: String, selected: String, itemStyle: LFFontViewItemStyle) {</span>

形参normal的前面加上#,如有疑问的,请参考《Swift:函数与方法》

好的,基本知识已经讲解完毕,下面我们来看看点击按钮后,怎样使得文字的大小随之发生变化。

由于LFFontView.swift是ViewController.swift的子View,所以我们应该可以想到使用代理或者闭包。

代理的实现方式

1)定义代理

protocol LFFontViewDelegate : NSObjectProtocol {
    func fontView(fontView: LFFontView, didSelectedItem item: LFFontViewItemStyle)
}

2)在LFFontView.swift定义代理属性

var delegate: LFFontViewDelegate?

3)在buttonClick方法中执行代理方法

delegate?.fontView(self, didSelectedItem: LFFontViewItemStyle(rawValue: sender.tag)!)

4)在ViewController.swift中遵守代理协议及实现代理方法

class ViewController: UIViewController,LFFontViewDelegate {

    @IBOutlet weak var testLabel: UILabel!

    override func viewDidLoad() {
        super.viewDidLoad()

        let fontView = LFFontView()
        fontView.delegate = self
        view.addSubview(fontView)
    }

    func fontView(fontView: LFFontView, didSelectedItem item: LFFontViewItemStyle) {
        switch(item){
            case .Small:
                testLabel.font = UIFont.systemFontOfSize(13)
            case .Middle:
                testLabel.font = UIFont.systemFontOfSize(16)
            case .Big:
                testLabel.font = UIFont.systemFontOfSize(18)
            case .SuperBig:
                testLabel.font = UIFont.systemFontOfSize(25)
        }
    }
}

这样就可以完成点击按钮,使得文字大小随之变化的效果了。但是程序刚启动的时候,应该选中第一个"Aa" 按钮并显示对应大小的文字,所以我们可以考虑使用“属性监听器”来完成第一次的点击事件。如果对属性监听器不怎么了解的朋友,可以参考《Swift:面向对象(属性)》。所以我们改造代理属性的定义,完成属性监听的工作,改造后的代码如下:

var delegate: LFFontViewDelegate? {
        didSet {
            buttonClick(buttons[0])
        }
    }

这里的didiSet在初始化的时候并不会执行,而是等到有具体的控制器成为它的代理的时候才会触发,也就是在ViewController中执行fontView.delegate = self 的时候会触发didSet的执行。

大家注意代理定义的时候,是继承自 NSObjectProtocol的,说明它还是沿用了objective-c时候的语法。其实我们定义的protocol完成可以不继承自任何内容。但有时候会出现问题。因为在Swift中的协议与objective-c的协议有所不同。在objective-c中的协议的实现者必须是类;而Swift中协议的实现者既可以是类,也可以是enum或者struct。所以为了严谨起见,我们定义的协议,可以直接指明实现者是类,所以改写协议的定义如下:

protocol LFFontViewDelegate : class {
    func fontView(fontView: LFFontView, didSelectedItem item: LFFontViewItemStyle)
}

闭包的实现方法 (闭包的知识如果有什么不理解,请参考《Swift:闭包(Closures)》)。

1) 定义闭包

var textClosure: (LFFontViewItemStyle -> ())?

2) 在buttonClick中调用闭包

func buttonClick(sender: UIButton) {
        selectedButton?.selected = false
        sender.selected = true
        selectedButton = sender

        textClosure?(LFFontViewItemStyle(rawValue: sender.tag)!)

        setNeedsLayout()
    }

3) 在ViewController中实现闭包方法

override func viewDidLoad() {
        super.viewDidLoad()

        let fontView = LFFontView()
        //fontView.delegate = self
        fontView.textClosure = {
            [unowned self]
            (FontStyle: LFFontViewItemStyle) -> () in
            switch(FontStyle){
            case .Small:
                self.testLabel.font = UIFont.systemFontOfSize(13)
            case .Middle:
                self.testLabel.font = UIFont.systemFontOfSize(16)
            case .Big:
                self.testLabel.font = UIFont.systemFontOfSize(18)
            case .SuperBig:
                self.testLabel.font = UIFont.systemFontOfSize(25)
            }
        }
        view.addSubview(fontView)
    }

4) 首次加载时候触发

在LFFontView.swift 中的 init(frame: CGRect) 中添加下面的最后一句代码即可。

 override init(frame: CGRect) {

        //super.init()  init是NSObject的默认构造方法
        super.init(frame: frame) // init(frame: CGRect)是UIView的默认构造方法

        self.frame = CGRectMake(0, kFontViewY, UIScreen.mainScreen().bounds.width, kFontViewH)

        initDetailViews()

        buttonClick(buttons[0])
    }

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-08-08 18:13:59

swift:UIKit中Demo(二)的相关文章

Swift:UIKit中Demo(一)

关于Swift的基本概念及语法知识.我在前面的章节中已经介绍了非常多.这一节和下一节主要有针对性的解说Swift在实际UIKit开发中的使用场景及注意点.先来看看Demo的终于效果图. Demo分析: 1. 界面上面有三个button,他们的宽度不一致. 2. 点击每一个button的时候.以下有红色下划线跟着"走动". 一. Storyboard中的设计 注意到,这个红色下划线是任意摆放的.没有刻意的设置它的位置及宽度.而这个红色下划线也就是一个简单的UIView. 二. 拖线工作

iOS开发——完整项目实战Swift篇&amp;百思不得姐Swift版总结(二)

百思不得姐Swift版总结(二) tabBar和NavBar配色方案 一.常规主题色使用点 应用在发布前都会对其主题色进行设置,以统一应用的风格(可能有多套主题).在主题色设置上有几个方面,如下: 1.TabBar部分,设置图片高亮.文本高度颜色 2.NavigationBar部分,设置导航栏颜色及字体颜色 3.应用标签等,设置字体的颜色 4.应用图片主题色 主题色的设置点,大体从上面四个方面着手,图片的主题色我们可通过图片更换的方式进行处理.而通过代码来处理的1-3条,有着不同的处理方法.大家

Swift学习笔记十二:下标脚本(subscript)

下标脚本就是对一个东西通过索引,快速取值的一种语法,例如数组的a[0].这就是一个下标脚本.通过索引0来快速取值.在Swift中,我们可以对类(Class).结构体(structure)和枚举(enumeration)中自己定义下标脚本的语法 一.常规定义 class Student{ var scores:Int[] = Array(count:5,repeatedValue:0) subscript(index:Int) -> Int{ get{ return scores[index];

Swift入门(十二)——利用Extension添加逆序输出字符串方法

Swift好像没有自带逆序输出字符串的方法,于是决定通过拓展(Extension)给String类添加一个逆序输出字符串的reverse方法. 首先新建一个Swift文件,命名规则不太清楚,于是暂且模仿OC叫做String+Operation吧,然后实现我们需要拓展的方法.下面先贴上代码,然后解释一下这段代码. //String+Operation.swifft import Foundation //逆序输出swift中的字符串 extension String{ func Reverse()

在 Swift 项目中实现侧滑菜单-利用 SWRevealViewController

你可以完全自己手动写一个侧滑菜单,但是现在在 GitHub 上面已经有很多免费的开源库了,如果不是有很特别的需求,大可不必新建一个轮子. 在这里我使用的这个第三方库名字叫做 SWRevealViewController,作者是 John Lluch.这个免费的类库提供了很方便快捷的方法去把侧滑菜单加入到你的 App 里面,而且它还提供了很多个性化的设置项.它是用 Objective-C 来写的,但是我们也可以很方便的在 Swift 项目中去使用它.你分分钟便可学会如何使用. 首先来看一下我们的

swift 集合类型(二)

说到swift的集合类型,就不得不谈到Dictionary.包含一个键值对组合的集合. var air = ["name":"warner","title":"Math"] var air = Dictionary<String,String>(minimumCapacity:3) 都可以初始化Dictionary.在swift中,Dictionary其实是一个结构:struct,继承自Collection.而Co

Swift 项目中常用的第三方框架

Swift 项目中可能用到的第三方框架 字数1004 阅读4091 评论17 喜欢93 这里记录下swift开发中可能用的框架 , 最近浏览了不少,积累在这里,以后用的时候方便查阅.顺便推荐给大家! 这里的框架都是纯swift的 , 感谢开源 ,感谢大神们 . 下拉刷新 BreakOutToRefresh 一个下拉刷新打砖块的swift库 SDRefreshView 简单易用的上拉和下拉刷新 ZLSwiftRefresh - 下拉刷新/上拉加载更多,支持自定义动画,集成简单 GearRefres

利用CocoasPod在Swift项目中使用CorePlot

最近在研究可用的第三方的图标控件,然后网上搜了之后,感觉功能比较强大的就是CorePlot了,于是就开始研究如何部署到程序中.网上关于这方面的教程比较少,大部分都是objective-c的,而且历史也比较久远,后来找到一篇老外写的blog,讲述在swift中如何使用CorePlot(http://blog.alwold.com/2014/08/07/using-coreplot-with-swift-in-ios/),研究了好久,总算成功安装了.下面就一步一步介绍. 1. 建立工程 首先建立一个

【转】 Android 基于google Zxing实现对手机中的二维码进行扫描--不错

原文网址:http://blog.csdn.net/xiaanming/article/details/14450809 转载请注明出处:http://blog.csdn.net/xiaanming/article/details/14450809 我之前写了一篇关于google Zxing扫描二维码的文章,效果是仿微信的效果,有兴趣的朋友可以去看看基于google Zxing实现二维码.条形码扫描,仿微信二维码扫描效果,有时候我们有这样子的需求,需要扫描手机中有二维码的的图片,所以今天实现的就