为了账号安全,请及时绑定邮箱和手机立即绑定

【译】学习使用Swift编写iOS app教程5:把它变漂亮

标签:
iOS

写在前面:
刚刚开始学习Swift开发,很幸运的是在网上闲逛的时候看到了Ray Wenderlich的这些关于iOS开发的教程,写的非常详尽,还很有趣,不时会搭配一些很贱的小表情,非常对我的胃口:-)在此对其进行一些翻译,纰漏之处,欢迎大家指正。
——Schuming


Update note: This tutorial was updated for iOS 9 and Swift 2 by Brian Moakley. Original post by Mike Jaoudi and Ry Bristow.
恭喜,你来到了教程系列的第四部分!
在教程的第一部分,你学习了通过Swift语言编程的基础知识,包括变量,if/else语句,循环,可选类型等等.
在教程的第二部分,你将新的Swift技能应用到一个简单的猜数字游戏中.
在教程的第三部分,你创建了一个简单的命令行app来记录people对象的名字和年龄.
在教程的第四部分,你制作了的你的第一个简单的iPhone App.
在第五部分,也是最后一部分内容里,从上一次的游戏入手,把它变得更吸引人一些怎么样?

教程的这个部分会叫你怎样为屏幕中的不同组件添加背景图片并将它做的更有趣一点.而且你还会学习到怎样实现背景音乐和音效.然我们开始吧!


开始
从上次项目收尾的地方开始,如果你没有这部分代码,从这里下载.
我建议你在开始前为项目文件夹做一个备份.这样的话,在你开始改变app界面之前,你还可以保留一个原始版本.这不仅可以让给你比较两个版本的不同,如果你在更改界面的时候发生了错误,还可以让你回顾以前的版本.
图片描述
然后,你需要下载Tap Me的资源文件,包括了在这个项目中你需要使用的图片和音轨.下载后,打开文件夹并选中里面的所有项目.将他们拖拽到文件树中的Supporting Files folder.
确保Copy items if needed这项被勾选, 如果你剪切或者删除了下载文件夹中的资源文件,这项仍可以保证你的项目在另一台电脑上工作.
图片描述


为Button添加背景图片
相较于给button添加一个纯色背景,使用一张经过处理的图片会好很多.给button添加背景图片时,你必须考虑到按键所处的状态.确认button的状态在Attributes Inspector中被设置为default.这是当什么事件都未产生时,button所处的状态.
图片描述
然后,找到包含Background的方框,把它设置为button_tap_deselected.png
图片描述
在你的前一个app中,你将button的背景设置为白色.现将它设置为default下的无颜色状态,这样它就不会在图片的后面再显示出来了.
图片描述
图片描述
哦!这个图片很难看清,因为button上的标题也是"Tap Me!".因为文字是图片的一部分,你可以继续,去除这个标题.
图片描述
图片描述
好多了!现在这个button比上一个app中的版本可读性更强,而且好看很多.不再是一个单调的,带有一些文本的白色方框了,而是一个有颜色的,三维的,带有漂亮文本内容的button.
下一步要做的,是给同一个button的highlighted状态设置一个背景图片.也就是用户点击时的button的状态.应该将 Background 部分f设置为button_tap_selected.png.
图片描述
你可能会注意到,你的button看起来有点被压扁了.这是因为你对width和height使用了硬编码(hardcoded)的constrains,而这个constrains比图片的尺寸要小.

Schuming注:Hard coding一般译为“硬编码”,就是指将原本应该作为变量的内容以固定值的形式写入到程序中。知乎上有人举了下面的栗子:

SOFT CODING:
MAX_VALUE = 10
if value <= MAX_VALUE:
    # do the right thing
else:
   raise ValueOutOfRangeException("value is greater than %d" %
MAX_VALUE)

HARD CODING:
if value <= 10:
    # do the right thing
else:
   raise ValueOutOfRangeException("value is greater than 10")

这个栗子里,如果使用hardcoding的方式,每次都把MAX_VALUE直接写成10,如果程序中有很多使用MAX_VALUE的地方,一旦MAX_VALUE发生改变,修改程序将会非常困难而且容易出错.

幸运的是,有一个简单地修正办法.所有的views都有一个固有内容大小(intrinsic content size),你可以将它看做是当前正在显示的元素的自动的constraint.对于图片来说,这个值就是图片本来的大小.
因此,相较于给width和height硬编码一些constraints,更好的选择是通过图片的intrinsic content size 来更好的管理图片的大小.
现在让我们来试一试,在文件导航器中(document navigator),找到button的width和height的constrints并点击删除他们:
图片描述
然后,通过点击右下角的三角形图标更新view controller中的所有的frames,用以匹配他们的constraints,并选择
All Views\Update Frames.
图片描述
Buildrun, 好好玩下这个button吧!
图片描述


为屏幕添加图片
有时,你可能希望给屏幕添加一些图片,这些图片不像buttons那样会做出反应.在这里,你可以使用UIImageView.在Object Library中找到 Image View 并将它拖拽到屏幕中.
你要用这个Image View组件去创建一个border(边框),因此你要调整它的位置和尺寸,让它从屏幕左边一直展开到屏幕右边,并且贴着屏幕的上部分.为另一个Image View组件做相同的处理,将它作为底部的border.
图片描述
把labels移动一下,腾出一些空间来.想实现这个的最简单的办法是使用size inspector中的Edit button来更新它们的constrains.选择Timer Label,在Constraints部分的Size Inspector中,点击Top Space to: Top Layout Guideconstraints中的Edit button .
图片描述
现在,设置顶部Image View组件的constraints.点击Pin button.首先,确保Constrain to margins选择框是没有被勾选的.下面,点击left,top,right T-bars.确保每一项的值为0.最后,选中Height constraint.将值设置为22.做好之后,点击写有Add 4 Constraints的button.
图片描述
如果你看到了橙黄色的线.像之前教程里那样update the frame.在底部的Image View组件上进行同样的操作.试着把constraints按照之前的提示进行设置.如果遇到困难,请看提示:

点击Pin button.首先,确保没有选中Constrain to margins checkbox.接下来,点击left, bottom ,和right T-bars.确保每一项的值都为0。最后,选中Height constraint.将值设置为22.这些都做好以后,点击 Add 4 Constraints.

图片描述

更新frame.

选择Inspector中的 top Image View, 将Image设置为 chekecker_top.png. 将模式设置为Mode to Aspect Fill.
图片描述
为底部的 Image View组件进行相同的操作,唯一不同的是将Image设置为checker_bottom.png.
再次运行一下app,看看这个漂亮的边框吧!
图片描述


通过程序设置背景颜色
你不需要总是使用Storyboard来改变app的外观.让我们把背景颜色改为紫色试一下.试着在ViewController.swift中的viewDidLoad()中添加这行代码:

view.backgroundColor = UIColor.purpleColor()

这行代码的作用是将view组件的backgroundColor 属性设置为UIColor 对象,UIColor 对象是通过purpleColor()返回生成的.
现在app看起来是这样的:
图片描述

尽管这验证了概念的正确,但是这看起来并不好看.然后,幸运的是,你也可以将view组件的背景设置为图片.让我们再来一次.将你设置背景颜色的代码替换为:

view.backgroundColor = UIColor(patternImage: UIImage(named: "bg_tile.png")!)

这行代码以图片平铺( tiles the image )的方式覆盖了view的背景.运行app,
图片描述
现在,继续用程序设置一下labels的背景.输入下面的代码:

scoreLabel.backgroundColor = UIColor(patternImage: UIImage(named: "field_score.png")!)
timerLabel.backgroundColor = UIColor(patternImage: UIImage(named: "field_time.png")!)

运行app,他现在是这样的.
图片描述


设置labels的位置和尺寸

还有一些有待优化的地方.其中一个就是labels的位置和尺寸很糟糕.scoreLabel 的位置明显太高了,尺寸形状跟他的image不匹配.为了修正这个情况,选择上面的label,使用Pin button和constraints来将width设置为133,height设置为46.
图片描述
选择下面的label,在 Project Navigator找到他当前对的constraints.点击delete删除它.
图片描述
使用Pin button来添加constraints,将他的width设置为146,height设置为102
图片描述
最后,清除选项,点击第三个button,选择 All Views in View Controller\Update Frames来添加constraints.
最后一个调整,你现在为labels设置的背景会让人几乎看不清上面黑色的文字.为了解决这个问题,将文字的颜色改为light blue,这样看起来和周围的界面更和谐.下面的设置的值是最好的.确保你将timeLabelscoreLabel都进行了修改.

图片描述
还要将每个label的布局调整到中间.
现在再来运行app看一下效果和新设置的字体颜色.
图片描述


添加音效
音乐和音效会给你的app增色不少.现在这是app唯一缺少的了!
但是首先,你需要音频文件.下载这些文件,将这三个文件添加到你的项目中.
这三个文件是:背景音乐,每次用户点击button的beep 音效,还能让游戏者感到些小紧张的,每秒钟的倒计时beep音效.
音效的使用需要在 view controller的代码中完成.打开ViewController.swift.在文件顶部,你会注意到这样一行代码:

import UIKit

你还需要使用一个import语句来添加AVFoundation框架.AVFoundation是代表音频和视频的Apple框架.将代码添加到前一个import语句下:

import AVFoundation

就像importing UIKit可以让你使用 UIButton 和UILabel,importing AVFoundation可以让你使用非常有用的在AVAudioPlayer类,接下来,你需要为三个音效创建实例变量.在类的代码段中,写三行代码来创建新的实例变量,写到其他实例变量的声明之后.

var buttonBeep : AVAudioPlayer?
var secondBeep : AVAudioPlayer?
var backgroundMusic : AVAudioPlayer?

由于AVAudioPlayer 可能不可用,因此实例变量被声明为optionals.接下来,你需要在viewDidLoad 函数前添加helper函数.

  func setupAudioPlayerWithFile(file:NSString, type:NSString) -> AVAudioPlayer?  {
    //1
    let path = NSBundle.mainBundle().pathForResource(file as String, ofType: type as String)
    let url = NSURL.fileURLWithPath(path!)

    //2
    var audioPlayer:AVAudioPlayer?

    // 3
    do {
      try audioPlayer = AVAudioPlayer(contentsOfURL: url)
    } catch {
      print("Player not available")
    }

    return audioPlayer
  }

这个函数返回了一个AVAudioPlayer 对象(通过->声明的),接受两个参数:一个文件名和类型.让我们看一下它做了什么.

  1. 你需要知道音频文件的绝对路径,NSBundle.mainBundle() 会告诉你可以从项目中的那个地方找到.AVAudioPlayer 需要知道知道一个URL形式的路径,因此绝对路径会被转换为URL 格式.
  2. 你会注意到audioPlayer 是一个optional类型.可能会出现基于设备创建的AVAudioPlayer 实例化失败的情况.
  3. 你在这里创建了AVAudioPlayer.由于创建对象可能产生一个error,所以你要使用do关键词来开始.接下来,你尝试创建player.如果player创建失败,你会catch error.着这种情况下,error仅仅是想console打印信息,但是真正的应用程序中,你会在代码段中对error进行处理.这段error handling代码是在Swift2.0中新引入的.
  4. 顺利的话,AVAudioPlayer 对象会被返回.
    现在你有了创建AVAudioPlayer 对象的方法,是时候使用它了!在viewDidLoad()函数中添加这部分代码,放置到setupGame()上面.
if let buttonBeep = self.setupAudioPlayerWithFile("ButtonTap", type:"wav") {
  self.buttonBeep = buttonBeep
}
if let secondBeep = self.setupAudioPlayerWithFile("SecondBeep", type:"wav") {
  self.secondBeep = secondBeep
}
if let backgroundMusic = self.setupAudioPlayerWithFile("HallOfTheMountainKing", type:"mp3") {
  self.backgroundMusic = backgroundMusic
}

你在这里创建了几个players.如果创建成功,对象会被赋值为实例变量.
现在的viewDidLoad中,你的代码中有三个音效准备被你调用了!
第一个,buttonBeep.应该在button被点击时触发.通过添加下面的代码,更新buttonPressed 函数,使得音效触发.

buttonBeep?.play()

通过在变量名后添加一个问号,你可以在optional对象上调用函数方法.如果对象存在,方法就会被调用.如果不存在,代码就会被忽略.
还有两个音效需要添加进去.secondBeep 音效要在倒计时开始后启动.将代码添加到subtractTime函数中的if语句前,实现对音效的调用:

secondBeep?.play()

基本完成了!
最后一步是添加背景音乐.每次新游戏开始时播放这段音乐,在setupGame()函数中添加代码.将这些代码方在setupGame函数体的下面:

backgroundMusic?.volume = 0.3
backgroundMusic?.play()

你可以通过调整背景音乐的音量来让beep音效被听得更清楚.改变backgroundMusicvolume属性是一个好办法.它可以被设置为 0 (关闭)1.0 (最大音量), 但是 0.3是一个很好的起始音量.
现在最后一次运行app,体验一下app那些很棒的特性.
图片描述


接下来做些什么?
恭喜!你完成了你的第一个iPhone app.通过将各个基本的功能组合成一个漂亮的带有音效的app.这里有完整的项目代码,你可以和你的项目比较一下.
你的app有还有很多可以更改的地方,比如添加或改变一些图像,添加不同的等级,甚至修改音效,脑洞无限大!
现在,你可能先看一下 iOS Apprentice 系列, 它会进加深入的阐述制作iOS apps.它也可以给那些初学者使用,你可以通过注册我们的newsletter来免费获取它的第一部分.
这期间,你有任何问题或评论,请来论坛中进行讨论!

点击查看更多内容
7人点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
Linux系统工程师
手记
粉丝
9
获赞与收藏
211

关注作者,订阅最新文章

阅读免费教程

感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消