簡體   English   中英

調整UITableView標頭的大小並包含UITextView(iOS7 + AutoLayout)

[英]Resize UITableView Header AND containing UITextView (iOS7 + AutoLayout)

我一直在努力解決這個問題,我想確保我這樣做是正確的。 作為參考,我使用AutoLayout和Storyboard,它是一個僅限iOS7的應用程序。

我有一個帶標題視圖的UITableView,並且HeaderView的UI連接在故事板中。 我在故事板中留下了標題,它包含一些元素,其中一個是不可滾動的UITextView。

以下是它在故事板中的基本外觀截圖:

截圖

我將標題視圖的背景變暗為深灰色,因此它很突出。

UITextView的文本可以是動態的,因此其高度需要根據文本的大小而改變。 但棘手的部分是表的標題視圖也需要調整其高度,具體取決於文本的大小。 我已經嘗試了一些帶有約束的不同東西,但它並沒有真正正常工作(除非我禁用AutoLayout並以編程方式重新調整大小,我真的很想避免)。

當然,我希望盡可能使用盡可能少的代碼。 我並不依賴於使用表視圖標題,盡管它可以很好地滿足我的需求,因為我希望它和它包含的textview能夠滾動下面的實際細節。 但總而言之,如果有一種更簡單的方法來實現這一點(即使用uilabel),我將很樂意改變底層結構。

對方法的任何想法? 沒有找人幫助我的答案; 如果可能的話,只是尋找一些好的起點。 提前致謝!

前段時間我找到了新的解決方案,也許它需要調整動畫並且是實驗性的,但是,對於某些情況它很好,所以試一試:

  1. 將headerView添加到UITableView。
  2. 將一個子視圖添加到headerView,讓我們稱之為包裝器。
  3. 使用它的子視圖(通過自動布局)調整包裝器的高度。
  4. 當autolayout完成布局時,將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 @try@catch 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

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

然后你只需設置tableViewHeader的框架。

如上所述,在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時,使用預先制作的單元格放入你將在最后一個單元格中使用的值,因為UILabels使用sizeWithFont(iOS 7之前版本)或boundingRectWithSize(iOS 7.0+),以及用於UITextViews的sizeThatFits。 (對於將來閱讀此內容的任何人,請檢查這些方法是否已被更新的內容替換)

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

然后在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];

這將導致tableview檢查它具有的大小,並且僅在更改時更新單元格或頁眉/頁腳。

通過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中重新查看視圖層次結構。 現在你所謂的標題視圖在表視圖中。 你不希望這樣。

或者,因為看起來您正在使用靜態單元格,所以您可以使頂部靜態單元格顯示所謂的標題視圖的外觀。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM