2013-10-17 40 views
9

我一直在努力爭取一小會兒,我想確保我以正確的方式做到這一點。作爲參考,我將Storyboard與AutoLayout結合使用,它是一款僅適用於iOS7的應用程序。調整UITableView標題大小幷包含UITextView(iOS7 + AutoLayout)

我有一個帶有標題視圖的UITableView,HeaderView的用戶界面連接在情節提要中。我已經在故事板中留下了標題,並且它包含一些元素,其中一個元素是不可滾動的UITextView。

這裏是它如何基本上看起來情節板中的截圖:

screenshot

我黑暗的標題視圖的背景爲深灰色,因此脫穎而出。

UITextView的文本可以是動態的,所以它的高度需要根據文本的大小而改變。但棘手的部分是,表格的標題視圖也需要調整其高度,具體取決於文本的大小。我嘗試了幾個不同的約束條件,但它並不能正確工作(除非我禁用AutoLayout並以編程方式重新調整大小,我真的很想避免)。

我希望這樣做盡可能的乾淨,儘可能少的代碼是必要的。我沒有綁定使用表視圖標題,雖然它符合我的需求,因爲我希望它和它的包含textview滾動下面的實際細節。但是,所有人都說,如果有一個更簡單的方法來完成這個(即用一個uilabel),我會很樂意改變底層結構。

任何想法的方法?不尋找某人通過答案牽着我的手;如果可能的話,主要是尋找一些好的起點。提前致謝!

+0

描述或理想地插入一張圖片,說明如何將HeaderView「連接」在故事板中。 – bilobatum

+0

沒問題,對不起,我最初應該這樣做。從故事板添加的屏幕截圖。謝謝! – svguerin3

+0

這很有用。您在調用標題視圖時在技術上不是表視圖標題視圖。這只是您從對象庫中拖出的視圖。我會在我的回答中解釋更多。 – bilobatum

回答

30

前段時間我發現了新的解決方案,也許它需要扭捏作動畫,是實驗性的,但是,對於某些範圍內它的罰款的案件,所以給它一個嘗試:

  1. 添加headerView到一個UITableView 。
  2. 爲headerView添加一個子視圖,我們稱它爲包裝。
  3. 使包裝的高度通過其子視圖進行調整(通過自動 佈局)。
  4. 當自動佈局完成佈局時,將headerView的高度設置爲 包裝的高度。 (請參閱-updateTableViewHeaderViewHeight
  5. 重新設置headerView。 (見-resetTableViewHeaderView

下面是一些代碼:

- (void)viewDidLayoutSubviews 
{ 
    [super viewDidLayoutSubviews]; 

    [self updateTableViewHeaderViewHeight]; 
} 

/** 
tableView's tableViewHeaderView contains wrapper view, which height is evaluated 
with Auto Layout. Here I use evaluated height and update tableView's 
tableViewHeaderView's frame. 

New height for tableViewHeaderView is applied not without magic, that's why 
I call -resetTableViewHeaderView. 
And again, this doesn't work due to some internals of UITableView, 
so -resetTableViewHeaderView call is scheduled in the main run loop. 
*/ 
- (void)updateTableViewHeaderViewHeight 
{ 
    // get height of the wrapper and apply it to a header 
    CGRect Frame = self.tableView.tableHeaderView.frame; 
    Frame.size.height = self.tableHeaderViewWrapper.frame.size.height; 
    self.tableView.tableHeaderView.frame = Frame; 

    // this magic applies the above changes 
    // note, that if you won't schedule this call to the next run loop iteration 
    // you'll get and error 
    // so, I guess that's not a clean solution and could be wrapped in @[email protected] block 
    [self performSelector:@selector(resetTableViewHeaderView) withObject:self afterDelay:0]; 
} 

// yeah, guess there's something special in the setter 
- (void)resetTableViewHeaderView 
{ 
    // whew, this could be animated! 
    [UIView beginAnimations:@"tableHeaderView" context:nil]; 

     self.tableView.tableHeaderView = self.tableView.tableHeaderView; 

    [UIView commitAnimations]; 
} 

這一切最初的自動佈局傳球后無縫工作。後來,如果你改變包裝的內容,使它獲得不同的高度,它不會工作出於某種原因(猜測佈局UILabel需要幾個自動佈局傳遞或什麼)。我通過在下一次運行循環迭代中爲ViewController視圖調度setNeedsLayout來解決此問題。

我已經爲此創建了示例項目:TableHeaderView+Autolayout

+0

謝謝你的示例項目!我有一個問題 - 如何在自動佈局的標題中放入一個按鈕,並對點擊和動畫做出反應?現在點擊正在爲我工​​作,但沒有爲按鈕顯示觸摸動畫 –

+1

@AlexSorokoletov UITableView是一個UIScrollView的子類,所以它也可以選擇延遲觸摸事件傳送到它的子視圖。要解決這個問題,您可以將delaysContentTouches設置爲NO(或IB中的「延遲內容接觸」)。 –

+0

它的工作原理!你讓我的晚上!我的例子中的 –

0

我會建議以編程方式設置高度。 您可以使用boundingRectWithSize:options:context

來計算文本視圖的高度然後您只需設置tableViewHeader的框架。

+0

我實際上已經嘗試過,但它似乎不會影響視圖大小,除非AutoLayout完全禁用。 (我可能會丟失一些明顯的東西,雖然? – svguerin3

-4

表視圖標題視圖通過tableView:viewForHeaderInSection:delegate方法賦予表視圖。

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section 
{ 
    // create your header view here (read the docs on this method, there are some specific requirements)... 

} 

我不知道是否可以設計故事板中的標題視圖;我想你必須使用單獨的XIB文件或以編程方式進行。

換句話說,如果您需要提供表視圖標題視圖,我認爲您已經開始在代碼中創建約束。

另一方面,也許你並不真的需要一個表視圖標題視圖。也許,你所追求的僅僅是表格視圖上方的子視圖,當用戶滾動表格時它不會移動。爲此,您需要在IB中重新構建視圖層次結構。現在你所謂的標題視圖在表格視圖內。你不想那樣。或者,因爲它看起來像你正在使用靜態單元格,所以你可以讓頂部靜態單元格看起來像你所謂的標題視圖。

+0

我喜歡你最近使用頂部靜態單元格的想法(因爲它的確需要與表格一起滾動)。我其實想到了這一點,但最終試圖強制它進入我認爲這個單元格是有意義的,因爲我可以在任意約束條件下將它設置在故事板中。但是,愚蠢的問題 - 對於我的問題,同樣的概念是否適用於單元格?也就是說,我可以設置約束來重新調整TextView和單元格的大小,基於文本,如果我有它在那裏呢?如果是這樣,那裏的任何方向將不勝感激!謝謝! – svguerin3

+0

我發現這篇文章,這似乎解決了使用iOS7的表格視圖單元格動態高度http://www.brynbodayle.com/faster-uitableviews-with-ios-7/要再試一次,再次感謝! – svguerin3

+3

tableViewHeader與tableView節標題完全不同。我認爲OP在問前者,但你的迴應是針對後者。 –

-2

正如上面所說的,在UITableView中用於報頭的高度不通過自動佈局的控制,而是由

-(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section 

頁腳高度由

-(CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section 

最後細胞高度由

設置設定
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{ 

tableview從故事板,XIB文件或代碼加載單元格。它使用上述方法爲頁眉,頁腳和單元格設置框架的大小,並將它們的視圖大小設置爲適合該空間。

瞭解自動佈局不會更改這些尺寸是很重要的,它只處理用於佈局容器內視圖的規則。

如果您的單元格/頁眉/頁腳正在使用靜態大小,那麼這很容易。您只需鎖定所有子視圖的高度,將您的單元格設置爲您返回高度相同的大小...並且所有內容都看起來應該如何。

動態單元格/頁眉/頁腳需要更多工作。

基本上,你會被要求告訴tableview你的單元格/頁眉/頁腳的大小,然後再實際製作它,並調整所有子視圖的大小。

您可以通過在cellForRowAtIndexPath和heightForRowAtIndexPath方法中設置一個斷點來快速測試,高度首先被調用。

對於動態tableviewcell高度,一個常見的技巧是在viewDidLoad中創建一個單元並保存它以計算高度。然後,當您到達heightForRowAtIndexPath或heightForHeaderInSection時,請使用pre製作的單元格放入您將在最終單元格中使用的值,對於UILabels,請使用sizeWithFont(iOS 7之前)或boundingRectWithSize(iOS 7.0+),sizeThatFits for UITextViews。 (對於將來有人閱讀,請檢查這些方法是否未被更新的東西替代)

因此,將您想要的文本放入虛擬單元格中,獲取標籤和文字視圖的高度,在它們之間添加空格並在完成後返回最終尺寸。

然後在cellForRowAtIndexPath或headerForSection中重做值的設置,但是會顯示實際的單元格。

如果您的身高計算符合您的自動佈局設置,那麼所有東西都將完美地貼合在它的空間中。

如果要更改單元格或標題的高度後,它已經繪製,那麼你會希望通過執行類似更新實現代碼如下:

[self.tableView beginUpdates]; 
// change the data that will cause cell height to be different in heightForCellAtIndexPath or which will change a header or footer height calculation 
[self.tableView endUpdates]; 

這將導致實現代碼如下檢查大小它只有更新單元格或頁眉/頁腳如果更改。

+9

正如我在上面的另一條評論中指出的那樣,不要將* table view header與* a * table view ** section header **混淆。你的回答指的是後者,但是OP在詢問前者。 –