2012年3月17日 星期六

Filter4Cam 學習之 Scroll Horizontally Tables: Part 1

since: 2012/03/16
update: 2012/03/17

reference:
How To Make An Interface With Horizontal Tables Like The Pulse News App: Part 1

說明:
1. 原作者是建立 Universal 的專案, 在此簡化為僅為 iPhone 的專案.
2. 更新成採用 iOS 5 的 ARC 與 storyboard.
3. 詳細的說明, 還是要看原作者的文章.

A. 新增專案
      Xcode > File > New > Project...
      iOS > Application > Empty Application > Next
       Product Name: HorizontalTables
       Company Identifier: com.blogspot
       Device Family: iPhone
       Use Automatic Reference Couting: checked
       > Next > Create

-------------------------------------------------------------------------------------

B. 新增 Storyboard
   1. Xcode > File > New > File...
      iOS > User Interface > Storyboard > Next
       Device Family: iPhone > Next
       Save As: HorizontalTables.storyboard > Create

   2. 修改 HorizontalTables-Info.plist 檔案
       a. 先在右方 Key-Value 清單下方的空白處, 按下 control + 滑鼠左鍵,
           在跳出的選項中, 點選: Add Row
       b. 輸入一筆資料: Key 為: Main storyboard file base name,
           Value 為: HorizontalTables

   3. 開啓 AppDelegate.m 檔案, 修改如下:
....
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    //@update: comment it
    //self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];

    // Override point for customization after application launch.
    self.window.backgroundColor = [UIColor whiteColor];
    [self.window makeKeyAndVisible];
    return YES;
}
....
-------------------------------------------------------------------------------------

C. 新增
Navigation Controller
    1. Xcode > File > New > File...
        > iOS > Cocoa Touch > Objective-C class > Next
      Class: HorizontalTablesViewController
      Subclass of: UINavigationController
      > Next > Create

   2. 點選 HorizontalTables.storyboard 檔案, 修改如下:
        a. 從 Object Library 拖拉一個 NavigationController 到 UI 上.

       b. 選取 UI 上的 NavigationController 後, 點選右邊的 Identity Inspector,
            將 Class 由預設的 UINavigationController 改成之前新增的:
            HorizontalTablesViewController, 並將 Table View Controller 刪除掉.
            (說明: 可以不需要將 Table View Controller 刪除, 因為之後會再新增)

    3. 編譯並執行

-------------------------------------------------------------------------------------

D. 新增 TableView Controller
      1. Xcode > File > New > File...
          > iOS > Cocoa Touch > Objective-C class > Next
        Class: ArticleListViewController
        Subclass of: UITableViewController
        > Next > Create

    2. 開啓 ArticleListViewController.m 檔案, 修改成只剩下以下的程式碼.
#import "ArticleListViewController.h"

@interface ArticleListViewController ()

@end

@implementation ArticleListViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
}

- (void)viewDidUnload
{
    [super viewDidUnload];
}

#pragma mark - Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    //@update
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    //@update
    return 10;
}

@end

-------------------------------------------------------------------------------------

E. 新增 ArticleListViewController 子類別
      1. Xcode > File > New > File...
          > iOS > Cocoa Touch > Objective-C class > Next
        Class: ArticleListViewController_iPhone
        Subclass of: ArticleListViewController
        > Next > Create

    2. 開啓 ArticleListViewController_iPhone.h 檔案, 修改如下:
#import "ArticleListViewController.h"
//@add
#import "ArticleListViewController.h"

@interface ArticleListViewController_iPhone : ArticleListViewController

@end

    3. 開啓 ArticleListViewController_iPhone.m 檔案, 修改如下:
....
//@update
/*
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
    }
    return self;
}
*/
....
//@update
/*
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
*/
....
//@add
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";
   
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
   
    if (cell == nil)
    {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
    }
   
    cell.textLabel.text = @"Vertical Table Rows on iPhone";
   
    return cell;
}
....

    4. 開啓 HorizontalTables.storyboard 檔案,
        拖拉一個 Table View Controller
到 UI 的右邊.

        a. 並將此 Table View Controller 的類別由 UITableViewController
           改選為: ArticleListViewController_iPhone .
     
        b. 以及將 Table View Cell 的 Identifier 設為: Cell       

    5. 接著, 選取左邊的 HorizontalTablesViewController, 按住 control 拉到右邊的
         ArticleListViewController_iPhone 上, 在跳出的視窗中選取
         "Relationship - Root View Controller" .


    6. 將 Navigation Item 的 Title 改為 "Horizontal Tables".

    7. 編譯並執行:

-------------------------------------------------------------------------------------

F. 載入一些文章到 App 裡
     1. 下載原作者提供的檔案: resources for this project     

     2. 在專案建立一個 Resources 群組, 並將解壓縮後的 Articles.plist 檔案與
          Article Images 資料夾下所有的圖檔都 copy 到 Resources 群組內.
 
     3. 開啓 ArticleListViewController.h 檔案, 修改如下:
#import <UIKit/UIKit.h>

@interface ArticleListViewController : UITableViewController
{
    //@add
    NSDictionary *articleDictionary;
}
//@add
@property (nonatomic, strong) NSDictionary *articleDictionary;

@end

     4. 開啓 ArticleListViewController.m 檔案, 修改如下:
#import "ArticleListViewController.h"

@interface ArticleListViewController ()

@end

@implementation ArticleListViewController

//@add
@synthesize articleDictionary = _articleDictionary;

- (void)viewDidLoad
{
    [super viewDidLoad];
    //@add
     self.articleDictionary = [NSDictionary dictionaryWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"Articles" ofType:@"plist"]];
}

- (void)viewDidUnload
{
    [super viewDidUnload];
    //@add
    self.articleDictionary = nil;
}

#pragma mark - Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    //return 1;
    //@update
    return [self.articleDictionary.allKeys count];
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    //return 10;
    //@update
    NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:nil ascending:YES selector:@selector(localizedCompare:)];

    NSArray *sortedCategories = [self.articleDictionary.allKeys sortedArrayUsingDescriptors:[NSArray arrayWithObject:sortDescriptor]];
   
    NSString *categoryName = [sortedCategories objectAtIndex:section];
   
    NSArray *currentCategory = [self.articleDictionary objectForKey:categoryName];
   
    return [currentCategory count];
}

//@add
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
    NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:nil ascending:YES selector:@selector(localizedCompare:)];

    NSArray *sortedCategories = [self.articleDictionary.allKeys sortedArrayUsingDescriptors:[NSArray arrayWithObject:sortDescriptor]];
   
    NSString *categoryName = [sortedCategories objectAtIndex:section];
   
    return [categoryName substringFromIndex:1];
}

@end

     5. 開啓 ArticleListViewController_iPhone.m 檔案, 修改如下:
....
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";
   
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
   
    if (cell == nil)
    {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
    }
   
    //cell.textLabel.text = @"Vertical Table Rows on iPhone";
    //@add
    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];
   
    NSDictionary *currentArticle = [currentCategory objectAtIndex:indexPath.row];
   
    cell.textLabel.text = [currentArticle objectForKey:@"Title"];

    cell.imageView.image = [UIImage imageNamed:[currentArticle objectForKey:@"ImageName"]];
   
    return cell;
}
....

     6. 編譯並執行:

-------------------------------------------------------------------------------------

G. 增加一些視覺上的變化
      1. 在 Navigation bar 上客製圖檔: NavBar.png
          高度: iPhone 44 pixels; Retina 88 pixels.
          開啓 HorizontalTablesViewController.m 檔案, 修改如下:
....
- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view.

    //@add       
    UIImage *image = [UIImage imageNamed:@"NavBar.png"];
   
    if([self.navigationBar respondsToSelector:@selector(setBackgroundImage:forBarMetrics:)] ) {
       
        // set the title of the navigation bar to an empty UIView
        self.navigationBar.topItem.titleView = [[UIView alloc] init];
       
        [self.navigationBar setBackgroundImage:image forBarMetrics:UIBarMetricsDefault];
       
        // set the tint color to the same gray we use for the background,
        // this way the buttons on our navigation bar will have the same tint.
        self.navigationBar.tintColor = [UIColor colorWithRed:0.6745098 green:0.6745098 blue:0.6745098 alpha:1.0];;
    }
}
....
        編譯並執行:

      2. 調整 Status Bar 的顏色
         a. 開啓 HorizontalTables-Info.plist 檔案, 新增一筆資料如下:
            Key: Status bar style
            Value: Transparent black style (alpha of 0.5)

         b. 開啓 AppDelegate.m 檔案, 修改如下:
....
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    //@update: comment it
    //self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    // Override point for customization after application launch.
    //self.window.backgroundColor = [UIColor whiteColor];
    //@update
    self.window.backgroundColor = [UIColor colorWithRed:0 green:0.81 blue:0.42 alpha:1];
   
    [self.window makeKeyAndVisible];
   
    return YES;
}
....
         c. 編譯並執行:

      3. 客製 table view 的 section headers
           a. 開啓 ArticleListViewController_iPhone.m 檔案, 修改如下:
//@add
#define kHeadlineSectionHeight  26
#define kRegularSectionHeight   18
....
//@add
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
    return section == 0 ? kHeadlineSectionHeight : kRegularSectionHeight;
}
....
//@add
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
    UIView *customSectionHeaderView;
    UILabel *titleLabel;
    UIFont *labelFont;
   
    if (section == 0)
    {
        customSectionHeaderView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, tableView.frame.size.width, kHeadlineSectionHeight)];
       
        titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(10, 0, tableView.frame.size.width, kHeadlineSectionHeight)];

        labelFont = [UIFont boldSystemFontOfSize:20];
    }
    else
    {
        customSectionHeaderView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, tableView.frame.size.width, kRegularSectionHeight)];
       
        titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(10, 0, tableView.frame.size.width, kRegularSectionHeight)];
       
        labelFont = [UIFont boldSystemFontOfSize:13];
    } 
   
    customSectionHeaderView.backgroundColor = [UIColor colorWithRed:0 green:0.40784314 blue:0.21568627 alpha:0.95];
   
    titleLabel.textAlignment = UITextAlignmentLeft;
    [titleLabel setTextColor:[UIColor whiteColor]];
    [titleLabel setBackgroundColor:[UIColor clearColor]];  
    titleLabel.font = labelFont;
   
    NSSortDescriptor* sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:nil ascending:YES selector:@selector(localizedCompare:)];

    NSArray* sortedCategories = [self.articleDictionary.allKeys sortedArrayUsingDescriptors:[NSArray arrayWithObject:sortDescriptor]];
   
    NSString *categoryName = [sortedCategories objectAtIndex:section];
   
    titleLabel.text = [categoryName substringFromIndex:1];
   
    [customSectionHeaderView addSubview:titleLabel];
   
    return customSectionHeaderView;
}
....

           b. 編譯並執行:

沒有留言:

張貼留言

注意:只有此網誌的成員可以留言。