2012年3月24日 星期六

Filter4Cam 實作: 12. 濾鏡表單之五

since: 2012/03/24
update: 2012/04/19

reference: I touchs: Filter4Cam 學習之 Scroll Horizontally Tables: Part 2

客製化 TableViewCell 之二

A. 說明
      目前已經有垂直的 table view, 並且建立了包含有水平 table 的客製化
      UITableViewCell, 但是為了讓介面看起來更酷, 所以我們需要另一個
      客製化的 cell, 來將其放到水平的 table 裡. 

      架構一: 垂直的 table 包含客製化的 TableViewCell (HorizontalTableCell)

      架構二: 客製化的 TableViewCell (HorizontalTableCell) 包含水平的 table
                     (filter Table View)

      架構三: 水平的 table (filter Table View) 裡包含客製化的 cell (filter cell)

      接下來要先建立架構三中的客製化 cell (filter cell)

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

B. 建立 UITableViewCell 子類別

      1. Xcode > File > New > File...
          > iOS > Cocoa Touch > Objective-C class > Next
         Class: FilterCell
         Subclass of: UITableViewCell
         > Next > Create

      2. 開啓 FilterCell.h 檔案, 修改如下:
#import <UIKit/UIKit.h>
//@add
#import "ConstantDefined.h"

@interface FilterCell : UITableViewCell
{
    //@add
    // hold the sample picture for our filter
    UIImageView *sampleImage; // 濾鏡效果的圖例
   
    // the title of our filter
    UILabel *titleLabel;
}

//@add
@property (nonatomic, strong) UIImageView *sampleImage;
@property (nonatomic, strong) UILabel *titleLabel;

@end

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

@implementation FilterCell

//@add
@synthesize sampleImage = _sampleImage;
@synthesize titleLabel = _titleLabel;

//@add
// we are using a custom UITableViewCell, we must manually define
// the reuse identifier

- (NSString *)reuseIdentifier
{
    return @"FilterCell";
}

//@add
- (void)dealloc
{
    self.sampleImage = 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
}
*/

//@add: override the initWithFrame method with our custom one
- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code
        //@add
       
        // We allocate and initialize a new UIImageView and give it a custom frame.
        //
        // We don't position it at 0, 0 (the top left corner) but we give it a little bit
        // of padding,
this will allow for separation between each filter cell.         
        self.sampleImage = [[UIImageView alloc] initWithFrame:CGRectMake(kFilterCellHorizontalInnerPadding, kFilterCellVerticalInnerPadding, kCellWidth - kFilterCellHorizontalInnerPadding * 2, kCellHeight - kFilterCellVerticalInnerPadding * 2)];
       
        // 設為完全不透明, 能增進效能
        self.sampleImage.opaque = YES;
       
        // we add the sampleImage as a subview of the cell's content view
        [self.contentView addSubview:self.sampleImage];
       
        // We create a UILabel and for the frame we make some adjustments
        // so that it has some padding on the left side
        // (thus preventing text to start from the very edge of the cell)
        //
        // And we make the height of the title label just 37% of the total height
        // of the picture and we move it down a bit so it fits the bottom part of the cell.
        //
        // This will make the title not cover the entire article cell and it's image,
        // but just the bottom half part.
        self.titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, self.sampleImage.frame.size.height * 0.632, self.sampleImage.frame.size.width, self.sampleImage.frame.size.height * 0.37)];
       
        // then set the label as opaque
        self.titleLabel.opaque = YES;
       
        // change the background color to a semitransparent gray (半透明灰)
        self.titleLabel.backgroundColor = [UIColor colorWithRed:0 green:0.4745098 blue:0.29019808 alpha:0.9];
       
        // give it a white color for the text
        self.titleLabel.textColor = [UIColor whiteColor];
       
        // set its font to the default bold font with a size of 11 points
        self.titleLabel.font = [UIFont boldSystemFontOfSize:11];
       
        // allow the label to show in two lines
        self.titleLabel.numberOfLines = 2;
       
        // add it as a subview of the sampleImage.
        [self.sampleImage addSubview:self.titleLabel];
       
        // set the background color of the cell to something along the lines of our interface
        self.backgroundColor = [UIColor colorWithRed:0 green:0.40784314 blue:0.21568627 alpha:1.0];
       
        // change the size of the cell's background view to the same size as
        // our sampleImage

        self.selectedBackgroundView = [[UIView alloc] initWithFrame:self.sampleImage.frame];
       
        // give it the custom background color we added in our ConstantDefined.h
        // file earlier.

        self.selectedBackgroundView.backgroundColor = kHorizontalTableSelectedBackgroundColor;
       
        // rotate the cell 90 degrees clockwise (順時針旋轉 90 度)
        //
        // 因為這些 cells 會在已旋轉的 table view 裡, 如果在此不作旋轉的話,
        // 將會看到被逆時針旋轉 90 度的結果
        self.transform = CGAffineTransformMakeRotation(M_PI * 0.5);
    }
   
    return self;
}

@end

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

C. 最後一個步驟
      1. 開啓 HorizontalTableCell.h 檔案, 修改如下
#import <UIKit/UIKit.h>
//@add
#import "ConstantDefined.h"
#import "FilterCell.h"
....

      2. 開啓 HorizontalTableCell.m 檔案, 修改如下
....
//@add
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    // we used the same reuse identifier as we did in the FilterCell class.
    static NSString *cellIdentifier = @"FilterCell";
   
    // we create a standard UITableViewCell for now
    //UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
    //
    //@update
    // dequeueReusableCellWithIdentifier: method will returns a regular
    // UITableViewCell,
so we must cast it to our custom subclass(FilterCell). 
    FilterCell *cell = (FilterCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier];
   
    // If we don't get returned a reusable cell, 
    //
    // then we allocate and initialize one with a custom frame that positions it
    // at the very top left corner of its container and makes it
    // the same width and height as our cell.
    if (cell == nil)
    {
        //cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
        //@update
        cell = [[FilterCell alloc] initWithFrame:CGRectMake(0, 0, kCellWidth, kCellHeight)];
    }
   
    //cell.textLabel.text = @"The title of the cell in the table within the table :O";
    //@update
    // we just fetch the current filter dictionary from our filters array
    NSDictionary *currentFilter = [self.filters objectAtIndex:indexPath.row];

    cell.sampleImage.image = [UIImage imageNamed:[currentFilter objectForKey:@"ImageName"]];

    cell.titleLabel.text = [currentFilter objectForKey:@"Title"];
   
    return cell;
}
....

      3. 開啓 ViewController.h 檔案, 修改如下:
....
//@add
#import "Filter4CamHelper.h"
#import "ConstantDefined.h"
#import "HorizontalTableCell.h"
....

      4. 開啓 ViewController.m 檔案, 修改如下:
....
//@add
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section    
{
    // Return the number of rows in the section.
    //return 2;
    //@update: creating a sort descriptor which will sort the objects in ascending order(升冪)
    /*
    NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:nil ascending:YES selector:@selector(localizedCompare:)];
    NSArray *sortedCategories = [self.filterDictionary.allKeys sortedArrayUsingDescriptors:[NSArray arrayWithObject:sortDescriptor]];
    NSString *categoryName = [sortedCategories objectAtIndex:section];
    NSArray *currentCategory = [self.filterDictionary objectForKey:categoryName];
   
    return [currentCategory count];
    */
   
    //@update
    return 1;
}
....
//@add
- (void)awakeFromNib
{
    // changes the background color of our vertical table
    [self.filterListTableView setBackgroundColor:kVerticalTableBackgroundColor];
   
    // changes the height of each row so that it can now fit our custom Filter Cell.
    self.filterListTableView.rowHeight = kCellHeight + (kRowVerticalPadding * 0.5) + ((kRowVerticalPadding * 0.5) * 0.5);
}
....
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    //static NSString *CellIdentifier = @"Cell";
    //@update: create a reuse identifier for our cell
    static NSString *CellIdentifier = @"HorizontalCell";
   
    //UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    //@update: try to dequeue one
     HorizontalTableCell *cell = (HorizontalTableCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
   
    // if that's not possible we create one.
    if (cell == nil)
    {
        //cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
        //@update
         cell = [[HorizontalTableCell alloc] initWithFrame:CGRectMake(0, 0, tableView.frame.size.width, tableView.frame.size.height)];
    }
   
    //@add: sort our categories
    NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:nil ascending:YES selector:@selector(localizedCompare:)];
   
    // get the current category's array of filters
    NSArray *sortedCategories = [self.filterDictionary.allKeys sortedArrayUsingDescriptors:[NSArray arrayWithObject:sortDescriptor]];
   
    // fetching a single filter category name
    NSString *categoryName = [sortedCategories objectAtIndex:indexPath.section];
   
    // fetching filters for a single category
    NSArray *currentCategory = [self.filterDictionary objectForKey:categoryName];
   
    //NSDictionary *currentFilter = [currentCategory objectAtIndex:indexPath.row];
   
   
    //cell.textLabel.text = [currentFilter objectForKey:@"Title"];
    //cell.imageView.image = [UIImage imageNamed:[currentFilter objectForKey:@"ImageName"]];
    //@update:pass the entire array to our HorizontalTableCell
    cell.filters = currentCategory;
   
    return cell;
}

//@add(此處應該不會用到)
/*
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSLog(@"Filter List Row => section:%d row:%d", [indexPath section], [indexPath row]);
}
*/
....

      5. 編譯並執行

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

D. UI 調整 (update: 2012/03/25)
     移除 section header, 並調整 cell 位置

    1. 開啓 FilterCell.m 檔案, 修改如下:
....
//@add: override the initWithFrame method with our custom one
- (id)initWithFrame:(CGRect)frame
{
....
        // change the background color to a semitransparent gray (半透明灰)
        // (Filter Cell 標題標籤的背景顏色)
        //self.titleLabel.backgroundColor = [UIColor colorWithRed:0 green:0.4745098 blue:0.29019808 alpha:0.9];
        //@update
        self.titleLabel.backgroundColor = kFilterCellTitleLabelBackgroundColor;
....
}
....

    2. 開啓 ViewController.m 檔案, 修改如下:
....
//@add
- (UITableView *)filterListTableView
{   
    if (_filterListTableView == nil) {
        //_filterListTableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 380, self.view.frame.size.width, 100) style:UITableViewStyleGrouped];
      
        //@update: kOverlayTableViewRowHeight = 106                                   
        _filterListTableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 374, self.view.frame.size.width, kOverlayTableViewRowHeight) style:UITableViewStyleGrouped];
    }
    
    return _filterListTableView;
}....
//@add for setting camera Overlay
- (void)cameraOverlay
{   
    [self.filterLensImageView setFrame:CGRectMake(20, 80, 280, 280)];
    [self.view addSubview:self.filterLensImageView];
   
    //@add
    self.filterListTableView.delegate = self;
    self.filterListTableView.dataSource = self;
   
    //@add: kOverlayTableViewRowHeight = 106
    self.filterListTableView.rowHeight = kOverlayTableViewRowHeight;

    //@add: 將 section Header Height 設為 0
    self.filterListTableView.sectionHeaderHeight = 0;
   
    // 不透明度, 會影響到所有的 subview 及 table 內的元件
    //self.filterListTableView.alpha = 0.2;
   
    //@add: 取消捲軸功能
    self.filterListTableView.scrollEnabled = NO;

    //@add: 將 Table (最下方的)分隔線設為: 不透明灰 (update: 2012/04/19)
    self.filterListTableView.separatorColor = kVerticalTableSeparatorColor;

   
    //@add: changes the background color of our vertical table
    // 垂直方向 table view 的背景顏色, 目前設為: 不透明灰
    // 由於已設定 scrollEnabled = NO, 因此也看不到設定的顏色
    [self.filterListTableView setBackgroundColor:kVerticalTableBackgroundColor];
   
    [self.view addSubview:self.filterListTableView];
}
....

//@add: provides from UITableViewDataSource
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
    //return section == 0 ? kHeadlineSectionHeight : kRegularSectionHeight;
    //@update
    return 0;
}

//@add: provides from UITableViewDataSource
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
    /*
....
    */
   
    //@update
    return nil;
}
....
//@update: comment it
/*
- (void)awakeFromNib
{
....
}
*/
....

    3. 編譯並執行(有再調整過顏色)


沒有留言:

張貼留言

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