2015-04-15 99 views
0

我一直在處理一組允許UITableView及其相關類使用自動佈局和動態類型的類。它基於an answer on Stack Overflow,旨在添加自動佈局支持。使用大小分類計算UITableViewCell offscreen的高度

到目前爲止,它運行良好,但使用尺寸類時遇到了一些問題。首先是直接關係到表計算的高度:

當我創建一個新的UITableViewCell,但不要把它添加到任何意見,大小類是Any X Any,所以當我有一些子視圖或根據尺寸等級改變的約束條件,他們總是工作,就好像他們在Any x Any的情況。到目前爲止,我非常哈克解決方案是創建一個新的UIWindow,我由單元添加到:

UIWindow(frame: UIScreen.mainScreen().applicationFrame)

此功能正常,但我有幾個問題吧:

  • 我現在正在打造一個全新的UIWindow對象,這似乎效率不高
  • 每個細胞都有被添加到同一窗口
  • 當屏幕旋轉時,尺寸規格可能會改變(即iPhone 6個加),所以我需要監聽更改應用程序框架和更新我的窗口的框架(尚未實現)

是否有保證UITableViewCell知道它的大小類容易/更有效的方式,而不必創建新的UIWindow,還是更有效地做到這一點?也許我可以添加一個

目前大部分代碼都可以通過GitHub page被發現,但最相關的方法是:

DynamicTableViewController

private var cachedClassesForCellReuseIdentifiers = [String : UITableViewCell.Type]() 
private var cachedNibsForCellReuseIdentifiers = [String : UINib]() 
private var offscreenCellRowsForReuseIdentifiers = [String : UITableViewCell]() 

private var offScreenWindow: UIWindow = { 
    return UIWindow(frame: UIScreen.mainScreen().applicationFrame) 
}() 

override public func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat { 
    // This method is called with an NSMutableIndexPath, which is not compatible with an imutable NSIndexPath, 
    // so we create an imutable NSIndexPath to be passed to the following methods 
    let imutableIndexPath = NSIndexPath(forRow: indexPath.row, inSection: indexPath.section) 

    if let reuseIdentifier = self.cellReuseIdentifierForIndexPath(imutableIndexPath) { 
     if let cell = self.cellForReuseIdentifier(reuseIdentifier) { 
      self.configureCell(cell, forIndexPath: indexPath) 

      if let dynamicCell = cell as? DynamicTableViewCell { 
       let height = dynamicCell.heightInTableView(tableView) 
       return height 
      } else { 
       // Fallback for non-DynamicTableViewCell cells 
       let size = cell.contentView.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize) 
       let cellBoundsHeight = CGRectGetHeight(cell.bounds) 
       if size.height > 0 && size.height >= cellBoundsHeight { 
        // +1 for the cell separator 
        return size.height + 1 
       } else { 
        // In some situations (such as the content view not having any/enough constraints to get a height), the 
        // size from the systemLayoutSizeFittingSize: will be 0. However, because this can _sometimes_ be intended 
        // (e.g., when adding to a default style; see: DynamicSubtitleTableViewCell), we just return 
        // the height of the cell as-is. This may make some cells look wrong, but overall will also prevent 0 being returned, 
        // hopefully stopping some things from breaking. 
        return cellBoundsHeight + 1 
       } 
      } 
     } 
    } 

    return UITableViewAutomaticDimension 
} 

private func cellForReuseIdentifier(reuseIdentifier: String) -> UITableViewCell? { 
    if self.offscreenCellRowsForReuseIdentifiers[reuseIdentifier] == nil { 
     if let cellClass = self.cachedClassesForCellReuseIdentifiers[reuseIdentifier] { 
      let cell = cellClass() 

      self.offScreenWindow.addSubview(cell) 
      self.offscreenCellRowsForReuseIdentifiers[reuseIdentifier] = cell 
     } else if let cellNib = self.cachedNibsForCellReuseIdentifiers[reuseIdentifier] { 
      if let cell = cellNib.instantiateWithOwner(nil, options: nil).first as? UITableViewCell { 
       self.offScreenWindow.addSubview(cell) 
       self.offscreenCellRowsForReuseIdentifiers[reuseIdentifier] = cell 
      } 
     } 
    } 
    return self.offscreenCellRowsForReuseIdentifiers[reuseIdentifier] 
} 

DynamicTableViewCell

public func heightInTableView(tableView: UITableView) -> CGFloat { 
    var height: CGFloat! 
    if self.calculateHeight { 
     self.setNeedsUpdateConstraints() 
     self.updateConstraintsIfNeeded() 

     self.bounds = CGRectMake(0, 0, CGRectGetWidth(tableView.bounds), CGRectGetHeight(self.bounds)) 

     self.setNeedsLayout() 
     self.layoutIfNeeded() 

     let size = self.contentView.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize) 
     let boundsHeight = CGRectGetHeight(self.bounds) 

     if size.height > 0 && size.height >= boundsHeight { 
      // +1 for the cell separator 
      height = size.height + 1 
     } else { 
      // In some situations (such as the content view not having any/enough constraints to get a height), the 
      // size from the systemLayoutSizeFittingSize: will be 0. However, because this can _sometimes_ be intended 
      // (e.g., when adding to a default style; see: DynamicSubtitleTableViewCell), we just return 
      // the height of the cell as-is. This may make some cells look wrong, but overall will also prevent 0 being returned, 
      // hopefully stopping some things from breaking. 
      height = boundsHeight + 1 
     } 
    } else { 
     height = self.cellHeight 
    } 

    if height < self.minimumHeight && self.minimumHeight != nil { 
     return self.minimumHeight! 
    } else { 
     return height 
    } 
} 

該解決方案適用於iOS 7和8,以及任何未來的解決方案。這個限制也消除了UITraitCollection的使用,所以我還沒有沿着這條路線走下去(我甚至不確定它會有幫助)

回答

0

使用IOS 8和Autolayout您可以設置估計的行高和設置約束對於具有內容視圖的內部視圖,所以它將根據其內容進行縮放。這裏是我的答案Which is the best approach among Autolayout or calculating the height using NSAttributedString, to implement dynamic height of an UITableViewCell?

更新:爲IOS7你需要計算高度時,它即將到來,你可以做到這一點在 - (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath委託方法

#define HEIGHT_FOR_ONE_LINE 15; //define it according to your fonts 
#define HEIGHT_FOR_SINGLE_ROWCELL 32; 
#pragma mark - Table view data source 
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    NSString *textToView= [self.yourDataSourceArray objectAtIndex:indexPath.row]; 
    CGFloat screenWidth=[[UIScreen mainScreen]bounds].size.width; 
    CGFloat characterPerPoint= 10; 
    CGFloat widthTaken= characterPerPoint * textToView.length; 
    NSInteger numberOfLines= ceil(widthTaken/screenWidth); 
    CGFloat height=numberOfLines* HEIGHT_FOR_ONE_LINE; 
    height = height + HEIGHT_FOR_SINGLE_ROWCELL; 

    return height; 
} 
+0

我實現曾經使用的iOS 8的自動高度計算對於單元格,但我有幾個問題,我也需要這個與iOS 7一起工作,所以使用和iOS 8 only解決方案是不可能的 –

相關問題