View Controllers, 天啊!现在我们有了一列虫子了,如果点击一个虫子,就弹出一个屏幕可以编辑虫子的名字,图片,评分,那就更好了。 大部分情况下,在iPhone应用中,每一个"界面"(“screen”)都有一个“View Controller”类的对象代表那个界面。现在我们MasterViewController在启动时显示出来了,它包含了一个table view. 我们想当点击一个虫子时,它会打开DetailViewController, 显示这个虫子的一些信息。 当我们第一次运行这个模板工程时,它可以工作,但当我们改变了显示在table view的对象后,点击table view的某一行不再发送正确的对象给detail view(这是我们的bug,不是XCode’s NSDate 工程模板的bug)。我们会回头修复它。 每一个“View Controller”可以包含多个view。在我们的table view controller, 我们只有一个view – table view. 然而在我们的details view controller, 我们需要一组view – 一个view显示虫子的名字,一个view显示图片,一个view用来评分,和其他的一些view。 | ![]() ljb_iss
|
下载点材料说起这个,在详细内容里我们需要一个5星评分视图,但是iPhone默认没有提供。不过我最近写了一个名为《在iOS5里怎样创建自定义UIView:一个5星评分视图》的教程,所以我们在这里重复使用这个教程。 不要太担心这个教程(除非你喜欢这个教程)–相反你只需要下载我放在项目里的 Extra Stuff for Scary Bugs这个包。 继续,下载了这个包之后:
| ![]() 人头马没面
|
用Storyboard编辑器对我们的Detail View Controller进行布局好了 – 现在我们终于准备好开始了! 打开MainStoryboard.storyboard, 如果你将滚动条拉到足够靠右的位置,你会看到模板为我们默认生成了Detail View Controller,并且带有一个内容为“Detail view content goes here” 的标签: Storyboard编辑器提供了一种可视化的方式,以方便你用XCode构建UI。你可以把UI元素拖放到你的视图上,用你想要的方式设置它们的属性值,甚至你可以在View Controller类里把元素连接到属性。 理解这些最容易的方式是亲自试一下!首先,在view controller上点击一下,并且打开Editor\Canvas\Show Bounds Rectangles(译者注:指的是菜单栏上的Editor) – 这样我们在屏幕上布局控件的时候会容易些。 删除内容为“Detail view content goes here”的标签 – 我们不需要它! | ![]() 人头马没面
|
然后来看面板的右下部分,确保Object Libray的第三个选项卡是被选择了的。拖拽一个UITextField,UIImageView和一个UIView到文字屏幕上并如下图所示安排(文字栏Text Filed在上方) 然后选择侧边栏上部的UITextField,确保第四个选项卡(属性检查工具)被选择,如此我们可以修改某些属性。 设置字体为Custom\Helvetica\Bold\Size 18.0,文字居中,当编辑时,清除按钮的行为是"Appears While Editing",Capitalzation选择Words,如下 然后,点击第四个选项卡转到尺寸检查工具(Size Inspector)设置自动大小调整属性。如下 这样当我们的视图(View)旋转到横向显示时,文本框(Text Field)在屏幕上伸展会变得更宽。 | ![]() renxh_cn
|
下来让我们设置UIImageView. 在等四个tab页(Attributes Inspector) 设置模式为“Aspect Fit”, 在第四个tab (Attributes Inspector) 和第五个tab (Size Inspector) 设置自动缩放(autosizing) 属性为下面的值: 这会使Image View放大或者缩小时,在保持它的边界到屏幕的边界的距离不变的同时,按照图片的宽高比来缩放图片尽可能的填充可用的空间。 对于UIView, 跳转到第三个tab (Identity Inspector)设置类标示(Class Identity)为“RateView”,我们的五星评分view将显示在那里。然后再第五个tab (Size Inspector) 设置自动缩放(autosizing)属性为下面的值: 这使它缩放时,在保持一样的高度的情况下,左右拉伸。 到现在为止,一切都很棒!下来我们需要添加一些控件到屏幕上,这样用户可以点击UIImageView区域来改变图片。 | ![]() ljb_iss
|
我们有好几个办法来做实现这个功能,但最简单的一个是创建一个不可见的按钮覆盖在UIImageView上面, 然后设置好按钮点击时的回调函数。我们还可以添加一个UILabel 在图片底层,当没有图片显示时,这个UILabel显示“点击改变图片”(“Tap to Change Picture”). 所以从库里拖拽一个圆角矩形按钮(Round Rect Button),然后调整坐标和UIImageView一样。为了使它不可见,在第四个tab(Attributes Inspector) 修改类型为Custom。然后在第五个tab (Size Inspector)设置自动大小属性为下面的值: 最后,从库里拖拽一个UILabel, 放在UIImageView中间, 然后双击它编辑文本为"点击改变图片"(“Tap To Change Image.”) 然后修改文本对齐属性(text alignment)为居中(center). 同样在XIB中拖拽UILabel向上几个位置使它可以在UIImageView后面 (这个列表顺序是从底层到上层): 然后在第五个tab (Size Inspector) 设置自动大小(autosizing)属性为下面的值: | ![]() ljb_iss
|
往下进行前,你可以通过下面的方法再次检查所有的自动大小(autosizing)属性已经正确设置。先选择Detail View Controller, 然后在第四个tab (Attributes Inspector) 把方向从纵向的肖像方式(Portrait)修改为横向的风景画方式( Landscape): 如果有些地方不对的话,不要担心 – 只需要修改回肖像方式(Portrait)然后再次仔细检查设置。 酷! 我们已经添加完所有需要的控件,然后我们需要把这些控件和我们类中相应的outlet关联起来。 首先,我们要先切换到助手编辑器(Assistant Editor) (点击顶上工具栏“Editor” 段下的第二个按钮), 要确保它设置为Automatic\DetailViewController.h: | ![]() ljb_iss
|
然后按着control键,同时鼠标左键拖拽UITextField到DetailViewController.h, 在@end之前释放. 然后会弹出一个弹出窗口让你把UITextField关联到你的类中的一个属性。在名字(Name)编辑框里输入titleField, 然后点击 Connect按钮. 重复同样的步骤,关联image view (但是关联的outlet命名为imageView),关联Rate View (但是关联的outlet命名为rateView). 我们同样想当按钮点击时,关联到一个我们类的方法被回调。为了实现这个功能,按control键同时,左键拖拽按钮到@end之前 — 就像你关联其他view一样的操作—然而这次connection下拉列表选择Action,在name编辑框输入 addPictureTapped, 然后点击Connect按钮. 注意,事件(Event)下拉框缺省选择为“Touch Up Inside”。这个缺省选项是对的,因为这意味着,当用户的手指在按钮里面抬起时 (也就是,他们点击了这个按钮), 我们的方法被调用。 | ![]() ljb_iss
|
你也可以关联其他动作(actions)到回调函数。例如,在文本框的文字改变时会触发一个动作,我们想这时触发一个回调函数。 为了实现这个功能,按control键,拖拽UITextField到@end之前,在弹出窗口,同样设置为动作(Action). 缺省的事件(event)设置为Editing Did End – 修改它为Editing Changed. 修改这个方法的名字(Name)为titleFieldTextChanged, 然后点击Connect按钮. 我们最后要做的一件事是设置我们的类为文本框的委托(delegate)。有时只是接收view的动作的回调是不足够的 - 这些view可能还有些其他信息需要告诉我们,例如这次的文本框就是个例子。 为了实现这个功能,按control键同时点击Text Field,然后从弹出菜单的"delegate"菜单项的右边的小圆圈拖出一条线到Detail View Controller, 然后释放. 在这时,你的DetailViewController.h应该看起来像下面这样:
| ![]() ljb_iss
|
通过Storyboard编辑器创建这些,它已经自动为我们关联好属性和控件了,但你可以按control键同时点击Detail View Controller来查看这些联接. 这些东西叫“outlets” . 我们需要对这部分做一些微调,标志我们的view controller实现了一些代理(delegates); 添加一个属性表示图片选取控件(image picker);和修改我们的detailItem的类型为ScaryBugDoc, 因为这个类型就是我们要显示的详情项。所以最后修改为下面的样子:
| ![]() ljb_iss
|
实现详情视图我要将对 DetailViewController.m 做一些更改。这里的代码较多,那么我们一步一步来看。 1) 导入头文件
2) 设置评分视图
3) 启用自动旋转
4) 设置初始 UI 状态
5) 处理文本视图与评分视图
textFieldShouldReturn 将在用户按软键盘上的“Return”键时调用,我们调用 resignFirstResponder 隐藏软键盘。 rateView:ratingIsChanged 将在用户选择一个新的评分后通过我们设置的 RateView’s delegate 调用,所以我们在这里更新对应的模型属性。 | ![]() 夜狼
|
如果您想了解, #pragma marks 是用于 XCode 的特别标记,用于在 XCode 编辑器的函数列表中产生一个用于组织目的的分隔线: 6) 显示图片选择器和处理返回结果
最后,我们实现图片选择器的图片已选择与取消回调。无论哪种方式,选关闭(dismiss)模式视图控制器。如果用户选择了一个图片,我们将获取全尺寸的图片和一个缩略图(用之前我们加入的 UIImageExtras 类产生)并同时更新模型与视图。 天啊 - 你看的代码快头疼了?别急 - 我们就快完成了。 | ![]() 夜狼
|
整合我们的详情视图这个还是很容易的。首先打开 MainStoryboard.storyboard , 选择 Master View Controller 中的 Table View Cell。Control-drag 这个单元格到 Detail View Controller, 将设置一个弹出选项问您需要使用的连接方式: Push, Modal, 或 Custom 。 选择 Push ,您应该看一个箭头连接了两个视图控制器: 现在我们只需要让选择行的虫子数据传递到详情视图控制器。打开 MasterViewController.m 并做以下更改:
| ![]() 夜狼
|
下一个,之前我们设置了当行选中时我们 Push 到详情视图控制器到堆。当它发生时将调用 prepareForSegue ,所以我们可以在这里获取详情视图控制器将做任何我们需要的设置。 在这里,我们只需要简单的设置一下选中的虫子。 终于,完成了!编译并运行您的项目,如果一切正常,您将能够进入虫子详情视图,更改虫子的名称、图片并对它们评分,并可能随意旋转您的设备! Where To Go From Here?这里包括完成本教程部分的完成 示例项目 。 如果以上有让你困惑的内容或如果你希望我将一些内容讲得更详细,请告诉我们。 本教程最终部分, 我们将介绍如何添加和删除虫子,添加一个图标和默认图像到我们的项目中,并正确处理长时间运行的操作! |