1. 程式人生 > >動態調整UITableViewCell的高度及字型大小設定

動態調整UITableViewCell的高度及字型大小設定

1 建立並新增一個UILabel作為單元格cell的子檢視;
2 在UITableView的委託方法: (CGFloat)tableView:(UITableView*)tableViewheightForRowAtIndexPath: (NSIndexPath *) indexPath中計算高度
3 在UITableView的委託方法: (UITableViewCell*)tableView:(UITableView*)tableViewcellForRowAtIndexPath: (NSIndexPath *) indexPath中計算UILabel的框大小。

下面我要詳細介紹這些步驟:

在普通的圖表中,你可以簡單地用下面的方法設定單元格內label的文字內容:

[[cell textLabel] setText:@"Text for the current cell here."];

也許你認為這樣做就可以完全控制UILabel了,但是我發現我的任何要改變UILabel框大小的嘗試都失敗了,因此這並不是實現動態調整大小的一個好的候選方案。

我們需要設計一個UILabel然後把它新增到單元格的內容檢視中。要實現它需要呼叫-cellForRowAtIndexPath,大致內容如下所示:

- (UITableViewCell *)tableView:(UITableView
*)tv cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell; UILabel *label = nil; cell = [tv dequeueReusableCellWithIdentifier:@"Cell"]; if (cell == nil) { cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:@"Cell"] autorelease]; label = [[UILabel
alloc] initWithFrame:CGRectZero]; [label setLineBreakMode:UILineBreakModeWordWrap]; [label setMinimumFontSize:FONT_SIZE]; [label setNumberOfLines:0]; [label setFont:[UIFont systemFontOfSize:FONT_SIZE]]; [label setTag:1]; [[cell contentView] addSubview:label]; } }

這並不是完整的程式碼因為我們僅僅在建立單元格的時候初始化它的label,這段程式碼對應呼叫-dequeueReusableCellWithIdentifier之後的判斷模組if(cell == nil)。
在這裡我想強調兩點:第一個,我們可以注意到label有一個標籤與其對應,因為呼叫了-setTag:1。當cell不等於nil時這個標籤可以用到。第二點,我們通過呼叫[[cell contentView] addSubview:label]來將label新增到單元格的內容檢視中,這個只是在label初始化的時候用到。每呼叫這個函式都會新增label 到子檢視序列中。下面我們會將這段程式碼補充完整,但之前先讓我們看一下如何設定cell的高度。

計算cell的高度

在一個複雜的cell中,計算高度可能比較困難,但是你只需要關心那些高度會變化的部件就可以了。在我的例子中,唯一需要處理的就是新增到單元格中的label。我們根據文字的大小來計算cell 的高度,而文字的大小取決於文字的長度和文字字型。NSString類提供了函式-sizeWithFont來方便我們獲取cell 的大小。下面的程式碼介紹了函式-heightForRowAtIndexPath:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;
{
  NSString *text = [items objectAtIndex:[indexPath row]];

  CGSize constraint = CGSizeMake(CELL_CONTENT_WIDTH - (CELL_CONTENT_MARGIN * 2), 20000.0f);

  CGSize size = [text sizeWithFont:[UIFont systemFontOfSize:FONT_SIZE] constrainedToSize:constraint lineBreakMode:UILineBreakModeWordWrap];

  CGFloat height = MAX(size.height, 44.0f);

  return height + (CELL_CONTENT_MARGIN * 2);
}

你會注意到我們用到了幾個常量來計算cell 的大小,它們的定義如下所示:

#define FONT_SIZE 14.0f
#define CELL_CONTENT_WIDTH 320.0f
#define CELL_CONTENT_MARGIN 10.0f

常量CELL_CONTENT_WIDTH是整個cell的寬度。CELL_CONTENT_MARGIN是我們定義的頁邊空白,FONT_SIZE是我們採用文字的字型大小。

首先我們要建立一個內容寬度的約束條件。CGSizeMake的第一個參量是總共的內容寬度減去兩個頁邊空白。因為左邊和右邊各有一個頁邊空白。第二個引數是我們提供的最大數值。這個約束條件在後面的函式-sizeWithFont中將會用到。在-sizeWithFont中我們設定為 UILineBreakModeWordWrap來獲取在允許自動換行的情況和上面提到的約束條件下正確的大小。最後我們使用MAX巨集設定cell的高度,並且保證cell 的高度不會小於44個畫素,因為它返回size.height和44兩個數中的最大值。最後,我們將上下的頁邊空白考慮進去得到最後的結果。

為了使得讀者形象化的瞭解頁邊空白,下面一個截圖可以看出有一個邊界環繞著label。呼叫[[label layer] setBorderWidth:2.0f]可以顯示該邊界從而方便我們看到頁邊空白。

計算並設定UILabel框大小

在前面我們用來計算高度的方法也是我們用來設定UILabel框大小的方法。下面將-cellForRowAtIndexPath程式碼補充完整:

- (UITableViewCell *)tableView:(UITableView *)tv cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
  UITableViewCell *cell;
  UILabel *label = nil;

  cell = [tv dequeueReusableCellWithIdentifier:@"Cell"];
  if (cell == nil)
  {
    cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:@"Cell"] autorelease];

    label = [[UILabel alloc] initWithFrame:CGRectZero];
    [label setLineBreakMode:UILineBreakModeWordWrap];
    [label setMinimumFontSize:FONT_SIZE];
    [label setNumberOfLines:0];
    [label setFont:[UIFont systemFontOfSize:FONT_SIZE]];
    [label setTag:1];

    [[label layer] setBorderWidth:2.0f];

    [[cell contentView] addSubview:label];

  }
  NSString *text = [items objectAtIndex:[indexPath row]];

  CGSize constraint = CGSizeMake(CELL_CONTENT_WIDTH - (CELL_CONTENT_MARGIN * 2), 20000.0f);

  CGSize size = [text sizeWithFont:[UIFont systemFontOfSize:FONT_SIZE] constrainedToSize:constraint lineBreakMode:UILineBreakModeWordWrap];

  if (!label)
    label = (UILabel*)[cell viewWithTag:1];

  [label setText:text];
  [label setFrame:CGRectMake(CELL_CONTENT_MARGIN, CELL_CONTENT_MARGIN, CELL_CONTENT_WIDTH - (CELL_CONTENT_MARGIN * 2), MAX(size.height, 44.0f))];

  return cell;
}

要注意if(cell == nil)模組是初始化程式碼,只在cell建立的時候執行一次。該模組外部程式碼每次都會執行只要在每次資料更新或者視窗拖拽之後呼叫了-cellForRowAtIndexPath。

也就是說,每次都需要設定label中文字內容以及設定label外框大小。注意如果label處於未初始化狀態,我們需要通過呼叫[cell viewWithTag:1]來獲取UILabel的控制代碼。這段程式碼跟前面計算高度的程式碼基本相同。

總結

動態計算單元格cell的高度真的並不困難。如果你有一個很複雜的cell,你只需要根據內容寬度和特定文字字型的大小來確定cell的高度。如果你不清楚你的外框顯示在什麼地方,只需要通過呼叫[[view layer] setBorderWidth:2.0f]來使外框顯示即可。這會有助於你瞭解繪圖過程以及更快地在更深的層次理解繪圖顯示的問題。
原文連結:

字型大小設定
經過驗證,這個windows和mac上的字號是統一的。

英文字型的1磅,相當於1/72 英寸,約等於1/2.8mm。

12PT的字打印出來約為4.2mm。網頁中12px的字才相當於12畫素。

雖然 四號=(14/72)*96=18.6px 更接近 19px,但是因為 18px 是點陣,所以系統還是優先顯示點陣字號的。

換句話說:四號=18px

中文字號VS英文字號(磅)VS畫素值的對應關係:

八號=5磅(5pt) ==(5/72)*96=6.67 =6px

七號=5.5磅 ==(5.5/72)*96=7.3 =7px

小六=6.5磅 ==(6.5/72)*96=8.67 =8px

六號=7.5磅 ==(7.5/72)*96=10px

小五=9磅 ==(9/72)*96=12px

五號=10.5磅 ==(10.5/72)*96=14px

小四=12磅 ==(12/72)*96=16px

四號=14磅 ==(14/72)*96=18.67 =18px

小三=15磅 ==(15/72)*96=20px

三號=16磅 ==(16/72)*96=21.3 =21px

小二=18磅 ==(18/72)*96=24px

二號=22磅 ==(22/72)*96=29.3 =29px

小一=24磅 ==(24/72)*96=32px

一號=26磅 ==(26/72)*96=34.67 =34px

小初=36磅 ==(36/72)*96=48px

初號=42磅 ==(42/72)*96=56px