update: 2012/03/26
reference:
How To Make An Interface With Horizontal Tables Like The Pulse News App: Part 2
A. 說明
1. 接續之前的專案: I touchs: Filter4Cam 學習之 Scroll Horizontally Tables: Part 1
2. 更新成採用 iOS 5 的 ARC 機制.
3. 詳細的說明, 還是要看原作者的文章.
---------------------------------------------------------------------------------------
B. 建立 UITableViewCell 子類別
1. 說明: a. 使用 Apple 預設的 cell 樣式, 可以有子標題或圖片, 但是無法嵌入一個
Table View.
b. 之後將會建立一個 UITableView, 旋轉後加入成為 cell 的 subview.
(需要覆寫 initWithFrame 方法)
2. Xcode > File > New > File...
> iOS > Cocoa Touch > Objective-C class > Next
Class: HorizontalTableCell
Subclass of: UITableViewCell
> Next > Create
Subclass of: UITableViewCell
> Next > Create
3. 開啓 HorizontalTableCell.h 檔案, 修改如下:
#import <UIKit/UIKit.h>
//@interface HorizontalTableCell : UITableViewCell
//@update
@interface HorizontalTableCell : UITableViewCell <UITableViewDelegate, UITableViewDataSource>
{
//@add
UITableView *horizontalTableView;
NSArray *articles;
}
//@add
@property (nonatomic, strong) UITableView *horizontalTableView;
@property (nonatomic, strong) NSArray *articles;
@end
4. 開啓 HorizontalTableCell.m 檔案, 修改如下:
#import "HorizontalTableCell.h"
@implementation HorizontalTableCell
//@add
@synthesize horizontalTableView = _horizontalTableView;
@synthesize articles = _articles;
#pragma mark - Table View Data Source
//@add
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [self.articles count];
}
//@add
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = @"ArticleCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
cell.textLabel.text = @"The title of the cell in the table within the table :O";
return cell;
}
#pragma mark - Memory Management
//@add
- (void)dealloc
{
self.horizontalTableView = nil;
self.articles = nil;
}
/*
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// Initialization code
}
return self;
}
*/
/*
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
*/
@end
---------------------------------------------------------------------------------------
C. 建立 Utility File
1. Xcode > File > New > File...
> iOS > C and C++ > Header File > Next
2. 開啓 ControlVariables.h 檔案, 修改如下:
// Width (or length before rotation) of the table view embedded
// within another table view's row
#define kTableLength 320
// Width of the cells of the embedded table view (after rotation, which means
// it controls the rowHeight property)
#define kCellWidth 106
// Height of the cells of the embedded table view (after rotation, which would
// be the table's width)
#define kCellHeight 106
// Padding for the Cell containing the article image and title
#define kArticleCellVerticalInnerPadding 3
#define kArticleCellHorizontalInnerPadding 3
// Padding for the title label in an article's cell
#define kArticleTitleLabelPadding 4
// Vertical padding for the embedded table view within the row
#define kRowVerticalPadding 0
// Horizontal padding for the embedded table view within the row
#define kRowHorizontalPadding 0
// The background color of the vertical table view
#define kVerticalTableBackgroundColor [UIColor colorWithRed:0.58823529 green:0.58823529 blue:0.58823529 alpha:1.0]
// Background color for the horizontal table view (the one embedded inside
// the rows of our vertical table)
#define kHorizontalTableBackgroundColor [UIColor colorWithRed:0.6745098 green:0.6745098 blue:0.6745098 alpha:1.0]
// The background color on the horizontal table view for when we
// select a particular cell
#define kHorizontalTableSelectedBackgroundColor [UIColor colorWithRed:0.0 green:0.59607843 blue:0.37254902 alpha:1.0]
3. 開啓 HorizontalTableCell.h 檔案, 修改如下:
#import <UIKit/UIKit.h>
//@add
#import "ControlVariables.h"
....
---------------------------------------------------------------------------------------
D. 建立 HorizontalTableCell 子類別
1. Xcode > File > New > File...
> iOS > Cocoa Touch > Objective-C class > Next
Class: HorizontalTableCell_iPhone
Subclass of: HorizontalTableCell
> Next > Create
2. 開啓 HorizontalTableCell_iPhone.m 檔案, 修改如下:
#import "HorizontalTableCell_iPhone.h"
@implementation HorizontalTableCell_iPhone
//@add
- (NSString *) reuseIdentifier
{
return @"HorizontalCell";
}
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
//@add
self.horizontalTableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, kCellHeight, kTableLength)];
self.horizontalTableView.showsVerticalScrollIndicator = NO;
self.horizontalTableView.showsHorizontalScrollIndicator = NO;
self.horizontalTableView.transform = CGAffineTransformMakeRotation(-M_PI * 0.5);
[self.horizontalTableView setFrame:CGRectMake(kRowHorizontalPadding * 0.5, kRowVerticalPadding * 0.5, kTableLength - kRowHorizontalPadding, kCellHeight)];
self.horizontalTableView.rowHeight = kCellWidth;
self.horizontalTableView.backgroundColor = kHorizontalTableBackgroundColor;
self.horizontalTableView.separatorStyle = UITableViewCellSeparatorStyleSingleLine;
self.horizontalTableView.separatorColor = [UIColor clearColor];
self.horizontalTableView.dataSource = self;
self.horizontalTableView.delegate = self;
[self addSubview:self.horizontalTableView];
}
return self;
}
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
// Drawing code
}
*/
@end
---------------------------------------------------------------------------------------
E. 建立 Article Cells
1. 說明:
目前已經有垂直的 table view, 並且建立了包含有水平 table 的客製化
UITableViewCell, 但是為了讓介面看起來更酷, 所以我們需要另一個客製化
的 cell, 來將水平的 table 放入.
2. 建立 UITableViewCell 子類別
Xcode > File > New > File...
> iOS > Cocoa Touch > Objective-C class > Next
Class: ArticleCell
Subclass of: UITableViewCell
> Next > Create
3. 開啓 ArticleCell.h 檔案, 修改如下:
#import <UIKit/UIKit.h>
@interface ArticleCell : UITableViewCell
{
//@add
// hold the thumbnail picture for our article
UIImageView *thumbnail;
// the title of our article
UILabel *titleLabel;
}
//@add
@property (nonatomic, strong) UIImageView *thumbnail;
@property (nonatomic, strong) UILabel *titleLabel;
@end
4. 開啓 ArticleCell.m 檔案, 修改如下:
#import "ArticleCell.h"
@implementation ArticleCell
//@add
@synthesize thumbnail = _thumbnail;
@synthesize titleLabel = _titleLabel;
//@add
- (NSString *)reuseIdentifier
{
return @"ArticleCell";
}
//@add
- (void)dealloc
{
self.thumbnail = nil;
self.titleLabel = nil;
}
/*
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// Initialization code
}
return self;
}
*/
/*
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
*/
@end
---------------------------------------------------------------------------------------
F. 建立 ArticleCell 子類別
1. Xcode > File > New > File...
> iOS > Cocoa Touch > Objective-C class > Next
Class: ArticleCell_iPhone
Subclass of: ArticleCell
> Next > Create
2. 開啓 ArticleCell_iPhone.m 檔案, 修改如下:
#import "ArticleCell_iPhone.h"
//@add
#import "ControlVariables.h"
@implementation ArticleCell_iPhone
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
//@add
self.thumbnail = [[UIImageView alloc] initWithFrame:CGRectMake(kArticleCellHorizontalInnerPadding, kArticleCellVerticalInnerPadding, kCellWidth - kArticleCellHorizontalInnerPadding * 2, kCellHeight - kArticleCellVerticalInnerPadding * 2)];
self.thumbnail.opaque = YES;
[self.contentView addSubview:self.thumbnail];
self.titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, self.thumbnail.frame.size.height * 0.632, self.thumbnail.frame.size.width, self.thumbnail.frame.size.height * 0.37)];
self.titleLabel.opaque = YES;
self.titleLabel.backgroundColor = [UIColor colorWithRed:0 green:0.4745098 blue:0.29019808 alpha:0.9];
self.titleLabel.textColor = [UIColor whiteColor];
self.titleLabel.font = [UIFont boldSystemFontOfSize:11];
self.titleLabel.numberOfLines = 2;
[self.thumbnail addSubview:self.titleLabel];
self.backgroundColor = [UIColor colorWithRed:0 green:0.40784314 blue:0.21568627 alpha:1.0];
self.selectedBackgroundView = [[UIView alloc] initWithFrame:self.thumbnail.frame];
self.selectedBackgroundView.backgroundColor = kHorizontalTableSelectedBackgroundColor;
self.transform = CGAffineTransformMakeRotation(M_PI * 0.5);
}
return self;
}
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
// Drawing code
}
*/
@end
---------------------------------------------------------------------------------------
G. 最後的步驟
1. 開啓 HorizontalTableCell_iPhone.m 檔案, 修改如下:#import "HorizontalTableCell_iPhone.h"
//@add
#import "ArticleCell_iPhone.h"
@implementation HorizontalTableCell_iPhone
//@add
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"ArticleCell";
ArticleCell_iPhone *cell = (ArticleCell_iPhone *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[ArticleCell_iPhone alloc] initWithFrame:CGRectMake(0, 0, kCellWidth, kCellHeight)];
}
NSDictionary *currentArticle = [self.articles objectAtIndex:indexPath.row];
cell.thumbnail.image = [UIImage imageNamed:[currentArticle objectForKey:@"ImageName"]];
cell.titleLabel.text = [currentArticle objectForKey:@"Title"];
return cell;
}
....
2. 開啓 ArticleListViewController.m 檔案, 修改如下:
....
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { //@update return 1; }....
3. 開啓 ArticleListViewController_iPhone.m 檔案, 修改如下:
//@add
#define kHeadlineSectionHeight 26
#define kRegularSectionHeight 18
#import "ArticleListViewController_iPhone.h"
//@add
#import "HorizontalTableCell_iPhone.h"
#import "ControlVariables.h"
....
//@add
- (void)awakeFromNib
{
[self.tableView setBackgroundColor:kVerticalTableBackgroundColor];
self.tableView.rowHeight = kCellHeight + (kRowVerticalPadding * 0.5) + ((kRowVerticalPadding * 0.5) * 0.5);
}
....
//@add
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
/*
....
*/
static NSString *CellIdentifier = @"HorizontalCell";
HorizontalTableCell_iPhone *cell = (HorizontalTableCell_iPhone *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[HorizontalTableCell_iPhone alloc] initWithFrame:CGRectMake(0, 0, tableView.frame.size.width, tableView.frame.size.height)];
}
NSSortDescriptor* sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:nil ascending:YES selector:@selector(localizedCompare:)];
NSArray* sortedCategories = [self.articleDictionary.allKeys sortedArrayUsingDescriptors:[NSArray arrayWithObject:sortDescriptor]];
NSString *categoryName = [sortedCategories objectAtIndex:indexPath.section];
NSArray *currentCategory = [self.articleDictionary objectForKey:categoryName];
cell.articles = currentCategory;
return cell;
}
....
4. 編譯並執行:
1. 說明: 當點選一篇文章時, title label 背景色不見了.
Xcode > File > New > File...
> iOS > Cocoa Touch > Objective-C class > Next
Class: ArticleTitleLabel
Subclass of: UILabel> Next > Create
3. 開啓 ArticleTitleLabel.h 檔案, 修改如下:
#import <UIKit/UIKit.h>
@interface ArticleTitleLabel : UILabel
{
}
//@add
- (void)setPersistentBackgroundColor:(UIColor*)color;
@end
4. 開啓 ArticleTitleLabel.m 檔案, 修改如下:
#import "ArticleTitleLabel.h"
//@add
#import "ControlVariables.h"
@implementation ArticleTitleLabel
//@add
- (void)setPersistentBackgroundColor:(UIColor*)color
{
super.backgroundColor = color;
}
//@add
- (void)setBackgroundColor:(UIColor *)color
{
// do nothing - background color never changes
}
//@add
- (void)drawTextInRect:(CGRect)rect
{
CGFloat newWidth = rect.size.width - kArticleTitleLabelPadding;
CGFloat newHeight = rect.size.height;
CGRect newRect = CGRectMake(kArticleTitleLabelPadding * 0.5, 0, newWidth, newHeight);
[super drawTextInRect:newRect];
}
/*
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
}
return self;
}
*/
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
// Drawing code
}
*/
@end
5. 開啓 ArticleCell.h 檔案, 修改如下:
#import <UIKit/UIKit.h>
//@add
@class ArticleTitleLabel;
@interface ArticleCell : UITableViewCell
{
//@add
// hold the thumbnail picture for our article
UIImageView *thumbnail;
// the title of our article
//UILabel *titleLabel;
//@update
ArticleTitleLabel *titleLabel;
}
//@add
@property (nonatomic, strong) UIImageView *thumbnail;
//@property (nonatomic, strong) UILabel *titleLabel;
@property (nonatomic, strong) ArticleTitleLabel *titleLabel;
@end
6. 開啓 ArticleCell_iPhone.m 檔案, 修改如下:
#import "ArticleCell_iPhone.h"
//@add
#import "ControlVariables.h"
#import "ArticleTitleLabel.h"
....
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
....
//self.titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, self.thumbnail.frame.size.height * 0.632, self.thumbnail.frame.size.width, self.thumbnail.frame.size.height * 0.37)];
//@update
self.titleLabel = [[ArticleTitleLabel alloc] initWithFrame:CGRectMake(0, self.thumbnail.frame.size.height * 0.632, self.thumbnail.frame.size.width, self.thumbnail.frame.size.height * 0.37)];
....
//self.titleLabel.backgroundColor = [UIColor colorWithRed:0 green:0.4745098 blue:0.29019808 alpha:0.9];
//@update
[self.titleLabel setPersistentBackgroundColor:[UIColor colorWithRed:0 green:0.4745098 blue:0.29019808 alpha:0.9]];
....
}
return self;
}
....
7. 開啓 HorizontalTableCell_iPhone.m 檔案, 修改如下:
#import "HorizontalTableCell_iPhone.h"
//@add
#import "ArticleCell_iPhone.h"
#import "ArticleTitleLabel.h"
....
8. 編譯並執行
I. 修正重覆出現列的情況
1. 開啓 ArticleListViewController.h 檔案, 修改如下:
#import <UIKit/UIKit.h>
@interface ArticleListViewController : UITableViewController
{
//@add
NSDictionary *articleDictionary;
NSMutableArray *reusableCells;
}
//@add
@property (nonatomic, strong) NSDictionary *articleDictionary;
@property (nonatomic, strong) NSMutableArray *reusableCells;
@end
2. 開啓 ArticleListViewController.m 檔案, 修改如下:
....
//@add
@synthesize articleDictionary = _articleDictionary;
@synthesize reusableCells = _reusableCells;
....
- (void)viewDidUnload
{
[super viewDidUnload];
//@add
self.articleDictionary = nil;
self.reusableCells = nil;
}
....
3. 開啓 ArticleListViewController_iPhone.m 檔案, 修改如下:
....
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
//@add
if (!self.reusableCells)
{
NSSortDescriptor* sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:nil ascending:YES selector:@selector(localizedCompare:)];
NSArray* sortedCategories = [self.articleDictionary.allKeys sortedArrayUsingDescriptors:[NSArray arrayWithObject:sortDescriptor]];
NSString *categoryName;
NSArray *currentCategory;
self.reusableCells = [NSMutableArray array];
for (int i = 0; i < [self.articleDictionary.allKeys count]; i++)
{
HorizontalTableCell_iPhone *cell = [[HorizontalTableCell_iPhone alloc] initWithFrame:CGRectMake(0, 0, 320, 416)];
categoryName = [sortedCategories objectAtIndex:i];
currentCategory = [self.articleDictionary objectForKey:categoryName];
cell.articles = [NSArray arrayWithArray:currentCategory];
[self.reusableCells addObject:cell];
}
}
}
....
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
/*
....
*/
//@update
HorizontalTableCell *cell = [self.reusableCells objectAtIndex:indexPath.section];
return cell;
}
....
4. 開啓 HorizontalTableCell.m 檔案, 修改如下: (update: 2012/03/26)
....
//@update: comment it
// Since we are no longer using the provided method for reusable cells,
// we don't need an identifier for them.
/*
- (NSString *)reuseIdentifier
{
return @"HorizontalCell";
}
*/
....
5. 編譯並執行:
---------------------------------------------------------------------------------------
J. 最後的效能調整: GCD (Grand Central Dispatch)
開啓 HorizontalTableCell_iPhone.m 檔案, 修改如下:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"ArticleCell";
//ArticleCell_iPhone *cell = (ArticleCell_iPhone *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
//@update
__block ArticleCell_iPhone *cell = (ArticleCell_iPhone *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[ArticleCell_iPhone alloc] initWithFrame:CGRectMake(0, 0, kCellWidth, kCellHeight)];
}
//NSDictionary *currentArticle = [self.articles objectAtIndex:indexPath.row];
//@update
__block NSDictionary *currentArticle = [self.articles objectAtIndex:indexPath.row];
dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
//cell.thumbnail.image = [UIImage imageNamed:[currentArticle objectForKey:@"ImageName"]];
//@update
dispatch_async(concurrentQueue, ^{
UIImage *image = nil;
image = [UIImage imageNamed:[currentArticle objectForKey:@"ImageName"]];
dispatch_async(dispatch_get_main_queue(), ^{
[cell.thumbnail setImage:image];
});
});
cell.titleLabel.text = [currentArticle objectForKey:@"Title"];
return cell;
}
沒有留言:
張貼留言
注意:只有此網誌的成員可以留言。