Submit Search
Upload
15 Subclassing UITableViewCell
•
0 likes
•
968 views
Tom Fan
Follow
子类化 UITableViewCell
Read less
Read more
Technology
Report
Share
Report
Share
1 of 67
Download now
Download to read offline
Recommended
component based html5 game engine
component based html5 game engine
hbbalfred
介绍Entity/Component游戏框架for html5 by @原木博皞(http://weibo.com/boisgames)
I os 02
I os 02
信嘉 陳
Backbone js and requirejs
Backbone js and requirejs
Chi-wen Sun
Backbonejs and RequireJS
I os 08
I os 08
信嘉 陳
07 View Controllers
07 View Controllers
Tom Fan
iOS 视图控制器
09 UITableView and UITableViewController
09 UITableView and UITableViewController
Tom Fan
Kissy design
Kissy design
yiming he
introduction to kissy design
Kissy简介
Kissy简介
jay li
KISSY简介
Recommended
component based html5 game engine
component based html5 game engine
hbbalfred
介绍Entity/Component游戏框架for html5 by @原木博皞(http://weibo.com/boisgames)
I os 02
I os 02
信嘉 陳
Backbone js and requirejs
Backbone js and requirejs
Chi-wen Sun
Backbonejs and RequireJS
I os 08
I os 08
信嘉 陳
07 View Controllers
07 View Controllers
Tom Fan
iOS 视图控制器
09 UITableView and UITableViewController
09 UITableView and UITableViewController
Tom Fan
Kissy design
Kissy design
yiming he
introduction to kissy design
Kissy简介
Kissy简介
jay li
KISSY简介
08 Notification and Rotation
08 Notification and Rotation
Tom Fan
iOS 通知和翻转,观察者模式, 通知中心, UIDevice 通知
iOS: Implementing a Custom View
iOS: Implementing a Custom View
Jussi Pohjolainen
01 A Simple iOS Application
01 A Simple iOS Application
Tom Fan
一个简单的 iOS 应用
04 Delegation and Core Location
04 Delegation and Core Location
Tom Fan
delegation 和 Core Location
06 Subclassing UIView and UIScrollView
06 Subclassing UIView and UIScrollView
Tom Fan
子类化 UIView 和 UIScrollView
PhoneGap 通信原理和插件系统
PhoneGap 通信原理和插件系统
Tom Fan
16 CoreData
16 CoreData
Tom Fan
iOS Core Data:关系对象模型
I os 09
I os 09
信嘉 陳
I os 14
I os 14
信嘉 陳
11 UINavigationController
11 UINavigationController
Tom Fan
使用 iOS 导航控制器
12 Camera
12 Camera
Tom Fan
iOS Camera, 拍照,获取图像
iOS App 開發 -- Storybard 基礎練習、APP 上架、IAP
iOS App 開發 -- Storybard 基礎練習、APP 上架、IAP
Ming-Sian Lin
iOS App 開發 -- Storybard 基礎練習 包含以下主題 1. Tab page 2. Page Control 3. Table 4. Gesture 5. Collection 6. Timer 跟 Thread 7. iAd 跟 IAP
10 Editing UITableView
10 Editing UITableView
Tom Fan
编辑 UITableView,编辑模式,增加行,删除行,移动行
I os 07
I os 07
信嘉 陳
005
005
Stronger Shen
13 UIPopoverController and Modal View Controller
13 UIPopoverController and Modal View Controller
Tom Fan
UIPopoverController 和 模态化视图控制器
I os 01
I os 01
信嘉 陳
I os 05
I os 05
信嘉 陳
I os 16
I os 16
信嘉 陳
掌星 移动互联网开发笔记-Vol001
掌星 移动互联网开发笔记-Vol001
rainx1982
掌星 移动互联网开发笔记-Vol001
Core data lightweight_migration
Core data lightweight_migration
Michael Pan
Michael Pan Facebook : https://www.facebook.com/pages/Developers-note/226724001803 Blogger : http://iosdevelopersnote.blogspot.tw/
各種酷炫圖表繪製技術 Silverlight Toolkit 與 MS Chart 控制項大探索
各種酷炫圖表繪製技術 Silverlight Toolkit 與 MS Chart 控制項大探索
Chui-Wen Chiu
More Related Content
Viewers also liked
08 Notification and Rotation
08 Notification and Rotation
Tom Fan
iOS 通知和翻转,观察者模式, 通知中心, UIDevice 通知
iOS: Implementing a Custom View
iOS: Implementing a Custom View
Jussi Pohjolainen
01 A Simple iOS Application
01 A Simple iOS Application
Tom Fan
一个简单的 iOS 应用
04 Delegation and Core Location
04 Delegation and Core Location
Tom Fan
delegation 和 Core Location
06 Subclassing UIView and UIScrollView
06 Subclassing UIView and UIScrollView
Tom Fan
子类化 UIView 和 UIScrollView
PhoneGap 通信原理和插件系统
PhoneGap 通信原理和插件系统
Tom Fan
Viewers also liked
(6)
08 Notification and Rotation
08 Notification and Rotation
iOS: Implementing a Custom View
iOS: Implementing a Custom View
01 A Simple iOS Application
01 A Simple iOS Application
04 Delegation and Core Location
04 Delegation and Core Location
06 Subclassing UIView and UIScrollView
06 Subclassing UIView and UIScrollView
PhoneGap 通信原理和插件系统
PhoneGap 通信原理和插件系统
Similar to 15 Subclassing UITableViewCell
16 CoreData
16 CoreData
Tom Fan
iOS Core Data:关系对象模型
I os 09
I os 09
信嘉 陳
I os 14
I os 14
信嘉 陳
11 UINavigationController
11 UINavigationController
Tom Fan
使用 iOS 导航控制器
12 Camera
12 Camera
Tom Fan
iOS Camera, 拍照,获取图像
iOS App 開發 -- Storybard 基礎練習、APP 上架、IAP
iOS App 開發 -- Storybard 基礎練習、APP 上架、IAP
Ming-Sian Lin
iOS App 開發 -- Storybard 基礎練習 包含以下主題 1. Tab page 2. Page Control 3. Table 4. Gesture 5. Collection 6. Timer 跟 Thread 7. iAd 跟 IAP
10 Editing UITableView
10 Editing UITableView
Tom Fan
编辑 UITableView,编辑模式,增加行,删除行,移动行
I os 07
I os 07
信嘉 陳
005
005
Stronger Shen
13 UIPopoverController and Modal View Controller
13 UIPopoverController and Modal View Controller
Tom Fan
UIPopoverController 和 模态化视图控制器
I os 01
I os 01
信嘉 陳
I os 05
I os 05
信嘉 陳
I os 16
I os 16
信嘉 陳
掌星 移动互联网开发笔记-Vol001
掌星 移动互联网开发笔记-Vol001
rainx1982
掌星 移动互联网开发笔记-Vol001
Core data lightweight_migration
Core data lightweight_migration
Michael Pan
Michael Pan Facebook : https://www.facebook.com/pages/Developers-note/226724001803 Blogger : http://iosdevelopersnote.blogspot.tw/
各種酷炫圖表繪製技術 Silverlight Toolkit 與 MS Chart 控制項大探索
各種酷炫圖表繪製技術 Silverlight Toolkit 與 MS Chart 控制項大探索
Chui-Wen Chiu
I os 10
I os 10
信嘉 陳
iPhone,ios,Object-C基础入门
iPhone,ios,Object-C基础入门
Lucien Li
Object-C基础快速入门
iPhone,ios,Object-c基础入门
iPhone,ios,Object-c基础入门
Lucien Li
iPhone,ios,Object-c基础入门
02 Objective-C
02 Objective-C
Tom Fan
Objective-C 基础:类,实例,对象,消息,初始化方法,类方法,数组,字符串和格式化字符串,访问器,异常
Similar to 15 Subclassing UITableViewCell
(20)
16 CoreData
16 CoreData
I os 09
I os 09
I os 14
I os 14
11 UINavigationController
11 UINavigationController
12 Camera
12 Camera
iOS App 開發 -- Storybard 基礎練習、APP 上架、IAP
iOS App 開發 -- Storybard 基礎練習、APP 上架、IAP
10 Editing UITableView
10 Editing UITableView
I os 07
I os 07
005
005
13 UIPopoverController and Modal View Controller
13 UIPopoverController and Modal View Controller
I os 01
I os 01
I os 05
I os 05
I os 16
I os 16
掌星 移动互联网开发笔记-Vol001
掌星 移动互联网开发笔记-Vol001
Core data lightweight_migration
Core data lightweight_migration
各種酷炫圖表繪製技術 Silverlight Toolkit 與 MS Chart 控制項大探索
各種酷炫圖表繪製技術 Silverlight Toolkit 與 MS Chart 控制項大探索
I os 10
I os 10
iPhone,ios,Object-C基础入门
iPhone,ios,Object-C基础入门
iPhone,ios,Object-c基础入门
iPhone,ios,Object-c基础入门
02 Objective-C
02 Objective-C
More from Tom Fan
HTML5 Web workers
HTML5 Web workers
Tom Fan
Web sockets
Web sockets
Tom Fan
Storage
Storage
Tom Fan
Semantics
Semantics
Tom Fan
Multimedia
Multimedia
Tom Fan
Intro to-html5
Intro to-html5
Tom Fan
Html5 history
Html5 history
Tom Fan
Geolocation
Geolocation
Tom Fan
File api
File api
Tom Fan
Deviceaccess
Deviceaccess
Tom Fan
Css3
Css3
Tom Fan
Webstorage
Webstorage
Tom Fan
Html5 最重要的部分
Html5 最重要的部分
Tom Fan
AT&T 的 HTML5 策略和应用现状
AT&T 的 HTML5 策略和应用现状
Tom Fan
PhoneGap 2.0 开发
PhoneGap 2.0 开发
Tom Fan
Android 平台 HTML5 应用开发
Android 平台 HTML5 应用开发
Tom Fan
HTML5 生态系统和应用架构模型
HTML5 生态系统和应用架构模型
Tom Fan
18 NSUserDefaults
18 NSUserDefaults
Tom Fan
iOS 设置
17 Localization
17 Localization
Tom Fan
国际化和本地化
14 Saving Loading and Application States
14 Saving Loading and Application States
Tom Fan
保存,加载和程序状态
More from Tom Fan
(20)
HTML5 Web workers
HTML5 Web workers
Web sockets
Web sockets
Storage
Storage
Semantics
Semantics
Multimedia
Multimedia
Intro to-html5
Intro to-html5
Html5 history
Html5 history
Geolocation
Geolocation
File api
File api
Deviceaccess
Deviceaccess
Css3
Css3
Webstorage
Webstorage
Html5 最重要的部分
Html5 最重要的部分
AT&T 的 HTML5 策略和应用现状
AT&T 的 HTML5 策略和应用现状
PhoneGap 2.0 开发
PhoneGap 2.0 开发
Android 平台 HTML5 应用开发
Android 平台 HTML5 应用开发
HTML5 生态系统和应用架构模型
HTML5 生态系统和应用架构模型
18 NSUserDefaults
18 NSUserDefaults
17 Localization
17 Localization
14 Saving Loading and Application States
14 Saving Loading and Application States
15 Subclassing UITableViewCell
1.
创建 UITableViewCell 的⼦子类 范圣刚,princetoad@gmail.com,
www.tfan.org
2.
• UITableView 显⽰示的是⼀一个
UITableViewCell 的列 表。对于⼤大多数应⽤用⽽而⾔言,带有 textLabel, detailTextLabel, 和 imageView 的基本单元格够⽤用 • 有时候我们想要能够显⽰示更详细信息,或者⼀一种 不同布局的单元格,这时候我们就要⼦子类化 UITableViewCell
3.
HomepwnerItemCell • 这⼀一节我们来创建⼀一个名为 HomepwnerCell
的可 以更有⼒力的显⽰示 BNRItem 实例的 UITableViewCell 的⼦子类 • 每⼀一个单元格将会显⽰示 BNRItem 的名称,以美元 记的价格,以及它的图⽚片的⼀一个缩略图
4.
创建 HomepwnerItemCell
5.
UIView 和 UITableViewCell
的⼦子类化 • UITableViewCell 也是 UIView 的⼀一个⼦子类。通常我 们⼦子类化 UIView (以及任何它的⼦子类)的时候, 我们会重写它的 drawRect: ⽅方法来⾃自定义 view 的 外形 • 但是⼦子类化 UITableViewCell 的时候,我们并不直 接修改单元格的外观
6.
⼦子类化 UITableViewCell 的⽅方法 •
每个单元格都有⼀一个名为 contentView 的⼦子视 图,它是构成⼀一个单元格⼦子类布局的视图对象的 容器 • 也就是说我们可以通过改变在单元格的 contentView 中的视图对象来⼦子类化 UITableViewCell。
7.
• ⽐比⽅方说,我们可以创建 UITextField,UILabel
和 UIButton 的实例并把它们加到 contentView • 甚⾄至我们可以创建⼀一个 UIView 的⼦子类,重写它的 drawRect: ,然后添加⼀一个它的实例到 contentView
8.
HomepwnerItemCell hierarchy
9.
为什么要加到 contentView? • 把⼦子视图添加到
contentView ,⽽而不是直接添加 到 UITableViewCell 的⼦子类很重要。因为单元格在 ⼀一个特定的时候将会调整 contentView 的⼤大⼩小。 • 例如,当 table view 进⼊入编辑模式时, contentView 会调整它的⼤大⼩小给编辑控件腾出空 间。
10.
• 如果我们直接把⼦子视图加到了 UITableViewCell,
编 辑控件将会遮掩这些⼦子视图。 • 单元格在进⼊入编辑模式时不能调整它的⼤大⼩小,但 是 contentView 可以并且也是这么做的。
11.
HomepwnerItemCell 类 • 打开
Homepwner.xcodeproj。⽣生成⼀一个新的 UITableViewCell 的⼦子类,命名为 HomepwnerItemCell
12.
配置 UITableViewCell ⼦子类的界⾯面
13.
• 创建⼀一个空的 XIB
⽂文件,命名为 HomepwnerItemCell.xib (Device Family 没有关系) • 打开 HomepwnerItemCell.xib 并且拖动⼀一个 UITableViewCell 实例到绘制区域 • 这个单元格需要显⽰示三个⽂文本元素和⼀一个图⽚片, 所以我们拖拽三个 UILabel 和 ⼀一个 UIImageView 到单元格上,分别显⽰示名称,价格,序列号和它 的图⽚片的缩略图(把序列号字体调稍⼩小点,颜⾊色深 灰)
14.
单元格上控件的⼤大⼩小问题 • ⾸首先我们来看⼀一下单元格⼤大⼩小的问题。 • 虽然单元格在
XIB ⽂文件上具有特定的⼤大⼩小,但是 我们并不知道在应⽤用程序⾥里⾯面实际的宽度和⾼高度 会是多少。
15.
• 因为我们的应⽤用将会运⾏行在 iPhone
和 iPad 上,⽽而 且在 iPad 还有可能是 portrait 和 landscape oritentation。 • 单元格需要进⾏行横向调整来匹配它所在的窗⼝口⼤大 ⼩小。这样我们就必须针对每个⼦子视图设置它的 autosizing mask • 在 size inspector ⾥里⾯面,我们来按照下⼀一⻚页的图⽰示 来更改 subview 的 autosizing mask
16.
HomepwnerItemCell 的Autoresizing masks •
image,name 和 serialNumber 位置都固定在左上 ⾓角;价格标签位置固定在右上⾓角; • name 和 serialNumber 宽度横向延伸
17.
更改 Class • 最后,我们点击
outline view 中的 cell,选择 identity inspector。把它的 Class 改成 HomepwnerItemCell
18.
导出 HomepwnerItemCell 的属性
19.
• 现在这个单元格视觉效果看起来还不错,但是我 们必须让它能够被⽤用起来。 • 也就是说当我们在 tableView:cellForRowAtIndexPath:
⾥里⾯面创建⼀一个 HomepwnerItemCell 的实例时,我们需要能够设 置每⼀一个 label 的 text 属性,以及 UIImageView 的 image。
20.
• 下⼀一步我们就是要来为每⼀一个⼦子视图创建和连接 HomepwnerItemCell
上的 outlets。 • 我们还是使⽤用前⼏几节⽤用到的 Controll-dragging 到 源⽂文件的⽅方式来创建它们的 outlets。 • 但是对于 HomepwnerItemCell 的 outlets,情况⼜又 有稍许不同:它们将会是 properites,⽽而不是简单 的实例变量。
21.
• 在 DetailViewController
中,没有 UITextFields 的 outlets 被曝露为属性,因为没有其它的对象会访 问它们。 • 在我们这种情况下,table view 的 data source 必 须配置每⼀一个 subview。通过把这些 subviews 导 出为 properties,数据源(ItemsViewController) 在需要的时候将可以访问。
22.
• 在 HomepwnerItemCell.xib
⽂文件打开的时候,在 HomepwnerItemCell.h 上 Option-click 。 • 从每⼀一个 subview Control-drag 到 HomepwnerItemCell.h 的⽅方法声明区域。 • 然后给每⼀一个 outlet 命名并且配置连接的每⼀一个 属性,让它们如下图所⽰示:
23.
Connections
24.
• 操作结束后的 HomepwnerItemCell.h
看起来应该 像下⾯面这样: @interface HomepwnerItemCell : UITableViewCell @property (weak, nonatomic) IBOutlet UIImageView *thumbnailView; @property (weak, nonatomic) IBOutlet UILabel *nameLabel; @property (weak, nonatomic) IBOutlet UILabel *serialNumberLabel; @property (weak, nonatomic) IBOutlet UILabel *valueLabel; @end
25.
使⽤用 HomepwnerItemCell
26.
• 在 ItemsViewController
的 tableview:cellForRoAtIndexPath: ⽅方法中,我们将 为表格中的每⼀一⾏行创建⼀一个 HomepwnerItemCell 的实例。 • 在 ItemsViewController.h 的顶部,导⼊入 HomepwnerItemCell 的头⽂文件 #import "HomepwnerItemCell.h"
27.
• 在之前的 tableview:cellForRowAtIndexPath:
的实现 中,我们⾸首先会询问 table view 它是否有可重⽤用 的 cell,然后如果没有的话我们再⽣生成⼀一个全新的 • 当使⽤用⼀一个 XIB ⽂文件来加载 UITableViewCell 的⼦子 类时,这个过程稍有不同:我们在 table 第⼀一次加 载时使⽤用⼀一个给定的 reuse identifier 向 UITableView 来注册这个 XIB ⽂文件。
28.
// 重写 viewDidLoad
为 HomepwnerItemCell 复⽤用标识注册 HomepwnerItemCell.xib - (void)viewDidLoad { [super viewDidLoad]; // 加载 xib ⽂文件 UINib *nib = [UINib nibWithNibName:@"HomepwnerItemCell" bundle:nil]; // 注册这个包含 cell 的 NIB [[self tableView] registerNib:nib forCellReuseIdentifier:@"HomepwnerItemCell"]; } • 在 ItemsViewController.m 中 重写 viewDidLoad 来 为 HomepwnerItemCell reuse identifier 注册 HomepwnerItemCell.xib
29.
• 要得到⼀一个 HomepwnerItemCell
的实例,我们向 table view 请求 dequeue ⼀一个符合 HomepwnerItemCell reuse identifier 的 Cell。 • 如果 table 有⼀一个可复⽤用的 HomepwnerItemCell 的 实例,就会返回它;如果没有的话,就会加载 HomepwnerItemCell.xib ,并且给你⼀一个 archived cell 的实例。 • 在 ItemsViewController.m 中,定位 tableView:cellForRowAtIndexPath: 并进⾏行如下修 改:
30.
- (UITableViewCell *)tableView:(UITableView
*)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { // // ⾸首先检查是否有可以重⽤用的单元格,如果存在的化就使⽤用 // UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"UITableViewCell"]; // if (!cell) { // cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"UITableViewCell"]; // } // else { // NSLog(@"重⽤用: %d", [indexPath row]); // } BNRItem *p = [[[BNRItemStore defaultStore] allItems] objectAtIndex:[indexPath row]]; // [[cell textLabel] setText:[p description]]; // 把原来相关的复⽤用代码删掉 // 获得⼀一个新的或者循环使⽤用的 cell HomepwnerItemCell *cell = [tableView dequeueReusableCellWithIdentifier:@"HomepwnerItemCell"]; // 使⽤用上⾯面的 BNRItem 配置这个单元格 [[cell nameLabel] setText:[p itemName]]; [[cell serialNumberLabel] setText:[p serialNumber]]; [[cell valueLabel] setText:[NSString stringWithFormat:@"$%d", [p valueInDollars]]]; return cell; }
31.
• 构建并运⾏行,单元格将会如下图所⽰示: • 要注意的两个问题:第⼀一,我们前⾯面使⽤用
UINib 来 进⾏行注册,XIB 的初始化底层调⽤用的也是 Nib;第 ⼆二,我们前⾯面的 XIB ⽂文件没有设置 File’s Owner, 因 为 table view 注册的时候只会扫描 UITableViewCell。所以 XIB ⽂文件⾥里⾯面也不能放置多 个 UITableViewCell。
32.
图像操作
33.
• 要在单元格⾥里⾯面使⽤用图像,我们可以使⽤用 image 的缩略图。 •
要创建⼀一个 BNRItem 图像的缩略图,我们需要绘 制⼀一个全尺⼨寸图⽚片 scale-down 的版本到 offscreen context, 然后在 BNRItem 实例中保持⼀一个指向这 个新图⽚片的指针。
34.
• 同样我们也需要⼀一个位置来存储这个缩略图,以 便在系统重启后可以重新加载。 •
全尺⼨寸的图⽚片我们保存在 BNRImageStore 中,必 要的时候我们可以把它 flush 掉;⽽而缩略图⾜足够 ⼩小,所以我们可以直接把它和 BNRItem 的其他实 例变量⼀一起 archive 起来。
35.
• 问题是缩略图是 UIImage
的⼀一个实例,⽽而 UIImage 并不符合 NSCoding 的 protocol,所以我们⽆无法在 NSCode 中直接对缩略图进⾏行编码。 • 我们可以把缩略图作为数据(PNG 格式)进⾏行编 码,并且把它封装在⼀一个 NSData 对象中,NSData 是符合 NSCoding 的。
36.
• 打开 BNRItem.h
, 声明两个新的属性:⼀一个 UIImage,⼀一个 NSData。 • 同样我们还需要⼀一个⽅方法来把全尺⼨寸的图⽚片转换 成⼀一个缩略图。 • 在 BNRItem.m 中,synthesize 这两个属性。 @interface BNRItem : NSObject <NSCoding> { } // 分别保存图⽚片和数据的两个属性,以及⼀一个把全尺⼨寸图⽚片转成缩略图的⽅方法 @property (nonatomic, strong) UIImage *thumbnail; @property (nonatomic, strong) NSData *thumbnailData; - (void)setThumbnailDataFromImage:(UIImage *)image; @synthesize thumbnail, thumbnailData;
37.
• 当我们为 BNRItem
选择⼀一个图⽚片的时候,我们就 把这个图⽚片赋给了 BNRItem。同时我们把它转成 ⼀一个缩略图,保存成它的 thumbnail。 • 同时还会⽣生成 PNG 格式的 NSData,并且把它保存 成 thumbnailData。 • thumbnailData 将会随着 BNRItem ⼀一起被 archive,⼀一起被从 archive 中加载,并且从它的数 据来重新创建 thumbnail。
38.
• 在 BNRItem.m
中,为 thumbnail ⽣生成⼀一个 getter ⽅方法,必要的时候从数据⽣生成它。 // ⾃自定义 getter ⽅方法 - (UIImage *)thumbnail { if (!thumbnailData) { return nil; } // 如果还没有从数据中⽣生成缩略图,创建它 if (!thumbnail) { // 从数据⽣生成图⽚片 thumbnail = [UIImage imageWithData:thumbnailData]; } return thumbnail; }
39.
• 现在我们来实现 setThumbnailDataFromImage:
⽅方 法 • 这个⽅方法将把⼀一个全尺⼨寸图⽚片⽣生成为缩略图,然 后把 thumbnail 指向这个图⽚片
40.
- (void)setThumbnailDataFromImage:(UIImage *)image {
CGSize origImageSize = [image size]; // thumnail 的矩形⼤大⼩小 CGRect newRect = CGRectMake(0, 0, 40, 40); // 计算缩放⽐比 float ratio = MAX(newRect.size.width / origImageSize.width, newRect.size.height / origImageSize.height); // ⽣生成⼀一个带缩放因⼦子的透明位图上下⽂文 UIGraphicsBeginImageContextWithOptions(newRect.size, NO, 0.0); // ⽣生成⼀一个圆⾓角矩形路径 UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:newRect cornerRadius:5.0]; // 后续绘制 clip 到这个圆⾓角矩形 [path addClip]; // 图⽚片放到缩略图中间 CGRect projectRect; projectRect.size.width = ratio * origImageSize.width; projectRect.size.height = ratio * origImageSize.height; projectRect.origin.x = (newRect.size.width - projectRect.size.width) / 2.0; projectRect.origin.y = (newRect.size.height - projectRect.size.height) / 2.0; // 把图⽚片绘制上来 [image drawInRect:projectRect]; // 从图⽚片上下⽂文获得图⽚片,作为我们的缩略图保存 UIImage *smallImage = UIGraphicsGetImageFromCurrentImageContext(); [self setThumbnail:smallImage]; // 得到该图⽚片 PNG 形式,把它作为我们可以 archive 的数据 NSData *data = UIImagePNGRepresentation(smallImage); [self setThumbnailData:data]; // 完成以后,清除图⽚片上下⽂文资源 UIGraphicsEndImageContext(); }
41.
• 在 DetailViewController.m
中,修改 imagePickerController:didFinishPickingMediaWithIn fo:,在采集到原始图⽚片时⽣生成缩略图 - (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info { // 如果存在就图⽚片,先从 BNRImageStore 中删除 NSString *oldKey = [item imageKey]; if (oldKey) { [[BNRImageStore sharedStore] deleteImageForkey:oldKey]; } // 从 info 字典中获得拾取的图⽚片 UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage]; // 拾取图⽚片以后⽣生成缩略图 [item setThumbnailDataFromImage:image];
42.
• 现在我们已经有了⼀一个可以⽤用在
ItemsViewController 的 table view 的缩略图。 • 在 ItemsViewController.m 中,更新 tableView:cellForRowAtIndexPath: // 使⽤用上⾯面的 BNRItem 配置这个单元格 [[cell nameLabel] setText:[p itemName]]; [[cell serialNumberLabel] setText:[p serialNumber]]; [[cell valueLabel] setText:[NSString stringWithFormat:@"$%d", [p valueInDollars]]]; // 设置缩略图 [[cell thumbnailView] setImage:[p thumbnail]]; return cell; } 构建并运⾏行,测试⼀一下缩略图的⽣生成和显⽰示
43.
• 最后我们来把缩略图的数据添加到 archive,修改
BNRItem.m。然后构建并运⾏行,退出再启动应⽤用 - (void)encodeWithCoder:(NSCoder *)aCoder { [aCoder encodeObject:itemName forKey:@"itemName"]; [aCoder encodeObject:serialNumber forKey:@"serialNumber"]; [aCoder encodeObject:dateCreated forKey:@"dateCreated"]; [aCoder encodeObject:imageKey forKey:@"imageKey"]; [aCoder encodeInt:valueInDollars forKey:@"valueInDollars"]; [aCoder encodeObject:thumbnailData forKey:@"thumbnailData"]; } - (id)initWithCoder:(NSCoder *)aDecoder { self = [super init]; if (self) { [self setItemName:[aDecoder decodeObjectForKey:@"itemName"]]; [self setSerialNumber:[aDecoder decodeObjectForKey:@"serialNumber"]]; [self setImageKey:[aDecoder decodeObjectForKey:@"imageKey"]]; [self setValueInDollars:[aDecoder decodeIntForKey:@"valueInDollars"]]; dateCreated = [aDecoder decodeObjectForKey:@"dateCreated"]; thumbnailData = [aDecoder decodeObjectForKey:@"thumbnailData"]; } return self; }
44.
从 UITableViewCells 转发
action
45.
• 我们希望⽤用户点击单元格中的⼀一个缩略图以后能 够看到⼀一个全尺⼨寸的图⽚片。 • 可以在
thumbnail 上⾯面加⼀一个透明的按钮 • 点击这个按钮以后,如果应⽤用运⾏行的 iPad 之上, 将会使⽤用 UIPopoverController 显⽰示⼀一个全尺⼨寸的 图⽚片。
46.
• 打开 HomepwnerItemCell.xib
,在 UIImageView 上 ⾯面拖拽⼀一个 UIButton,重新调整这个按钮的⼤大⼩小 让它正好和 UIIImageView 的⼤大⼩小完全⼀一致。 • 然后在 HomepwnerItemCell.h 上 Option-click 打开 assistant editor。从按钮 Control-drag 到⽅方法区 域,然后像下⾯面这样配置⼀一下。 - (IBAction)showImage:(id)sender;
47.
• 为了不让这个按钮掩盖下⾯面的图⽚片,在 attributes inspector
⾥里⾯面,把按钮的类型改成 Custom。 • 默认情况下,⼀一个 custom 的按钮不做任何绘制, 也就是说它是⼀一个透明的,上⾯面什么也没有的按 钮。
48.
• 现在的问题是 HomepwnerItemCell
不是⼀一个 controller,⽽而且也⽆无法访问任何拿到全尺⼨寸图⽚片 需要的数据。 • 解决⽅方法是给 HomepwnerItemCell ⼀一个到 ItemsViewController 的指针。 • 这样在 HomepwnerItemCell 收到从按钮来的 action message时,它会发⼀一个新的消息到 ItemsViewController,这样 controller 就可以获取 图⽚片并且把它在 UIPopoverController 中显⽰示。
49.
增加指针到单元格⼦子类
50.
• ⾸首先给 HomepwnerItemCell
指向 controller 的指 针,还有⼀一个指向 cell 所在的 table view 的指针。 • 在 HomepwnerItemCell.m 中,synthesizie 这些属 性 @property (weak, nonatomic) id controller; @property (weak, nonatomic) UITableView *tableView; @implementation HomepwnerItemCell @synthesize controller; @synthesize tableView;
51.
• 现在我们需要当 cell
被创建时来设置这些属性。 • 在 ItemsViewController.m 中,找到 tableView:cellForRowAtIndexPath: ⽅方法,添加下⾯面 代码: HomepwnerItemCell *cell = [tableView dequeueReusableCellWithIdentifier:@"HomepwnerItemCell"]; // 设置 HomepwnerItemCell 中传递消息⽤用的属性 [cell setController:self]; [cell setTableView:tableView]; // 使⽤用上⾯面的 BNRItem 配置这个单元格 [[cell nameLabel] setText:[p itemName]];
52.
转发消息到控制器 • 现在单元格已经知道它的控制器和它要在上⾯面显 ⽰示的
table view 了 • 当 showImage: 消息被发送到 HomepwnerItemCell 时,我们希望 HomepwnerItemCell 可以告诉 ItemsViewController 为在 index path 位置的单元 格显⽰示图⽚片
53.
• 在 HomepwnerItemCell.m
中实现 showImage: , 从 table view 拿到它的 index path,并且给 controller 发送 showImage:atIndexPath: 消息 - (IBAction)showImage:(id)sender { // 拿到该⽅方法的名字,“showImage” NSString *selector = NSStringFromSelector(_cmd); // selector 现在变成了 “showImage:atIndexPath:” selector = [selector stringByAppendingString:@"atIndexPath:"]; // 从字符串准备⼀一个 selector SEL newSelector = NSSelectorFromString(selector); // 拿到 indexPath NSIndexPath *indexPath = [[self tableView] indexPathForCell:self]; // // 调⽤用 controller 的⽅方法 // [[self controller] showImage:sender atIndexPath:indexPath]; // ⾸首先检查 if (indexPath) { if ([[self controller] respondsToSelector:newSelector]) { // 使⽤用 performSelector:withObject:withObject: 发送动态消息 [[self controller] performSelector:newSelector withObject:sender withObject:indexPath]; } } }
54.
• 我们先来验证⼀一下是不是⼀一切⼯工作正常,在
ItemViewController.m 中实现 showImage:atIndexPath: 来打印出⺫⽬目前的 index path • 然后构建并运⾏行,点击⼀一个缩略图,看⼀一下控制 台消息 // 实现 showImage:atIndexPath: - (void)showImage:(id)sender atIndexPath:(NSIndexPath *)ip { NSLog(@"即将为 %@ 显⽰示图⽚片", ip); }
55.
在popover controller中显⽰示图像
56.
• 现在 ItemsViewController
需要修改 showImage:atIndexPath: 来提取 BNRItem 和按钮被 按下的单元格相关联的图⽚片 • 然后在 UIPopoverController 中显⽰示它的图⽚片
57.
• 要在 popover
中显⽰示⼀一个图⽚片,我们需要⼀一个 UIViewController 作为 popover 的 content view controller,这个 UIViewController 要能够显⽰示图⽚片 • 我们新建⼀一个 UIViewController 的⼦子类,命名为: ImageViewController, 选择 UIViewController 作为 它的⽗父类,然后勾选“With XIB for user interface”
58.
• 打开新建的这个 ImageViewController.xib,
⾸首先拖 拽⼀一个 UIScrollView 到 View 上;然后拖拽⼀一个 UIImageView 到 UIScrollView 上
59.
ImageViewController XIB
60.
• 在配置像具有这种堆叠在⼀一起的视图的 XIB
⽂文件 时,很难对视图进⾏行选择,因为都是完全重叠 的。 • 这时候我们可以从 outline view ⾥里⾯面的 objects 开 始拖拽,⽽而不是从 canvas 区域的可视化部分 • 在 ImageViewController.h 中,给 interface 添加⼤大 括号,然后建⽴立连接。这些连接应该是 weak ⽅方式 的实例变量(imageView, scrollView)
61.
• 然后在 ImageViewController.h
中增加⼀一个属性来 持有这个 image @interface ImageViewController : UIViewController { __weak IBOutlet UIScrollView *scrollView; __weak IBOutlet UIImageView *imageView; } @property (nonatomic, strong) UIImage *image; @end
62.
• 当⼀一个 ImageViewController
的实例被创建时,它 会被赋予⼀一个 image。 • 显⽰示的时候,它将会调整 imageView 来适应图 ⽚片,然后告诉 scrollView 来更新它的 content size 来适配。
63.
• ⾸首先在 ImageViewController.m
中,synthesize 这 个 image 属性 • 然后实现 viewWillAppear: 来配置这些视图 @implementation ImageViewController @synthesize image; - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; CGSize sz = [[self image] size]; [scrollView setContentSize:sz]; [imageView setFrame:CGRectMake(0, 0, sz.width, sz.height)]; [imageView setImage:[self image]]; }
64.
• popover 完成以后,我们就可以继续完成我们的
showImage:atIndexPath: 了 • ⾸首先在 ItemsViewController.h 中声明它符合 UIPopoverControllerDelegate, 然后给它⼀一个实例 变量来持有这个 popover @interface ItemsViewController : UITableViewController <UIPopoverControllerDelegate> { UIPopoverController *imagePopover; }
65.
• 然后在 ItemsViewController.m
顶部导⼊入需要的头 ⽂文件 // 为 image popover 导⼊入相应头⽂文件 #import "BNRImageStore.h" #import "ImageViewController.h"
66.
• 然后完成 showImage:atIndexPath:的实现 //
实现 showImage:atIndexPath: - (void)showImage:(id)sender atIndexPath:(NSIndexPath *)ip { NSLog(@"即将为 %@ 显⽰示图⽚片", ip); // 实现 image popover if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad ) { // 从 index path 得到 item BNRItem *i = [[[BNRItemStore defaultStore] allItems] objectAtIndex:[ip row]]; NSString *imageKey = [i imageKey]; // 如果没有图⽚片,就不需要显⽰示 UIImage *img = [[BNRImageStore sharedStore] imageForKey:imageKey]; if (!img) { return; } CGRect rect = [[self view] convertRect:[sender bounds] fromView:sender]; // ⽣生成⼀一个新的 ImageViewController 然后设置它的 image ImageViewController *ivc = [[ImageViewController alloc] init]; [ivc setImage:img]; // 使⽤用 ImageViewController ⽣生成⼀一个 popover // 600*600 imagePopover = [[UIPopoverController alloc] initWithContentViewController:ivc]; [imagePopover setDelegate:self]; [imagePopover setPopoverContentSize:CGSizeMake(600, 600)]; [imagePopover presentPopoverFromRect:rect inView:[self view] permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES]; } }
67.
• 最后,在 ItemsViewController.m
中,实现⽤用户点 击屏幕上任何位置都把 popover 去掉的功能 • 构建并运⾏行,点击缩略图看⼀一下popover⾥里⾯面的 image,点屏幕上的其他任何地⽅方,可以把 popover 关闭 - (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController { [imagePopover dismissPopoverAnimated:YES]; imagePopover = nil; }
Download now