2015-05-03 2 views
1

Основная настройка такова: у меня есть UITableView с двумя прото-ячейками, с которыми я работаю (подумайте о приложении для обмена сообщениями, где один тип ячейки показывает сообщения, которые вы отправляете, и другие, сообщения, которые вы получаете). Теперь, очевидно, длина сообщения может варьироваться от одной строки до еще 100 строк, поэтому мне нужны переменные высоты ячеек.iOS UITableView не может вычислить правильную высоту ячейки для каждой ячейки

Первая попытка:

tableView.estimatedRowHeight = 75 
tableView.rowHeight = UITableViewAutomaticDimension 

Я использовал estimatedRowHeight в моем viewDidLoad(). Это прекрасно работает и очень хорошо вычисляет высоты ячеек. Но поскольку это приложение для обмена сообщениями, мне нужно прокрутить таблицуView до конца на viewDidLoad() и всякий раз, когда новое сообщение будет отправлено/отправлено. Но estimatedRowHeight беспорядок с прокруткой tableView донизу. Некоторые говорят, что это ошибка, некоторые говорят, что этого можно ожидать. Тем не менее, этот способ не будет работать для меня вообще.

Вторая попытка:

func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat

Я думал, чтобы вычислить высоту вручную так:

let measuerWidth = UIScreen.mainScreen().bounds 

var w = measuerWidth.size.width // this is so that we can limit label width to screen width so the text is forced to go to multiple lines 

// I probably should use my custom cell width here, but if I try to `dequeue` that cell it's frame contents are always `zero`. Is that a problem?   

let lbl = UILabel(frame: CGRect.zeroRect) 
lbl.text = chatMessages[indexPath.row][ChatRoomKeys.MESSAGE_TEXT] as? String 
lbl.font = UIFont.systemFontOfSize(20) 
lbl.numberOfLines = 0 
lbl.lineBreakMode = NSLineBreakMode.ByWordWrapping 
lbl.frame = CGRectMake(0, 0, w, 0) 
lbl.sizeToFit() 


return lbl.frame.height + 20 

Этот способ работает почти идеально, однако на высоте клетки раз не то, что он должен быть. Значение иногда, если текст - одна строка плюс одно слово, одно слово не будет отображаться, потому что высота ячейки была только для одной строки.

Есть ли лучший способ рассчитать высоту ячейки?

UPDATE: Вот скриншот любопытное, что происходит

enter image description here

как вы можете видеть на этикетке заканчивается x, но оригинальный текст увеличивается до y.

UPDATE 2:

enter image description here

Это прото-клетки, которые я использую, нижняя клетка просто зеркало верхней.

+0

Для попытки 1, что, если вы добавите «нижнюю часть вставки», чтобы прокрутить ее до конца? Кроме того, попытка 1 работает только в iOS8, поэтому, если вам нужен iOS7, вам нужен другой способ (не могу сказать, является ли Tryempt2 хорошей идеей, но это похоже на хороший старт) – Gasim

+0

Хорошо, если он не будет работать под iOS 8, тогда нет в этом направлении. Однако это хороший подход. – someguy234

+0

Ключ вычисляет 'CGRectMake (0, 0, w, 0)' width = 'w'. Я должен был вручную совать в инспекторе, чтобы выяснить, насколько ширина текстовой метки фактически занимает внутри ячейки. И 'w = (TABLE_WIDTH - (CELL_WIDTH - LABEL_WIDTH)' – someguy234

ответ

1

Я использую этот один:

- (CGFloat) tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
     if (indexPath.row == 2) 
    { 
     NSString *cellText = @"init some text"; 
     CGSize labelSize = [self calculateTextSize:cellText]; 

     return labelSize.height + 20.0f; 
    } 

    return 45; 
} 



- (CGSize) calculateTextSize: (NSString*) text 
{ 
    UIFont *cellFont = [UIFont fontWithName:@"HelveticaNeue" size:12.0]; 

    CGFloat width = CGRectGetWidth(self.tableView.frame) - 40.0f; 
    CGSize constraintSize = CGSizeMake(width, MAXFLOAT); 

    CGRect labelRect = [cellText boundingRectWithSize:constraintSize options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName:cellFont} context:NSLineBreakByWordWrapping]; 

    CGSize labelSize = labelRect.size; 

    return labelSize; 
} 

Edit:

CGFloat width = CGRectGetWidth(self.tableView.frame) - 40.0f; 

Расчет максимально возможной ширины текста, вы можете использовать self.view.frame или т.п. -40.0f - потому что у меня есть отступ от края = 20.0f

+0

'CGRectGetWidth' <- XCode не может найти это. Является ли это ярлыком для' self.tableView.frame.width'? – someguy234

+0

Получил это, но он все еще та же проблема.Я добавил скриншот выше для лучшей картины. – someguy234

+0

Проверьте атрибуты метки раскадровки «lines» = 0 – OMGHaveFun

1

Вы можете сделать это с автоматической высотой, как вы делали. См. Код ниже, когда появится ваше представление, в этом случае задайте UITableView для количества строк в разделе (0). Затем вы можете создать NSIndexPath для последней строки в этом разделе, затем попросите UITableView прокрутить этот путь указателя к представлению.Используя приведенный ниже код, вы все равно можете подсчитать высоту для UITableView.

import UIKit 

final class ViewController: UIViewController { 

    // MARK: - Constants 
    let kFromCellIdentifier = "FromCell" 
    let kToCellIdentifier = "ToCell" 

    // MARK: - IBOutlets 
    @IBOutlet private weak var tableView: UITableView! 

    override func viewDidLoad() { 
     super.viewDidLoad() 

     tableView.estimatedRowHeight = 75.0 
     tableView.rowHeight = UITableViewAutomaticDimension 
    } 

    override func viewWillAppear(animated: Bool) { 
     super.viewWillAppear(animated) 
     let numRows = tableView.numberOfRowsInSection(0) - 1 // -1 because numbering in the array starts from 0 not 1 
     let indexPath = NSIndexPath(forRow: numRows, inSection: 0) 
     tableView.scrollToRowAtIndexPath(indexPath, atScrollPosition: .Bottom, animated: false) 
    } 
} 

extension ViewController: UITableViewDataSource { 

    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 
     return 50 
    } 

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { 
     if indexPath.row % 2 == 0 { 
      let cell = tableView.dequeueReusableCellWithIdentifier(kFromCellIdentifier, forIndexPath: indexPath) as! CustomTableViewCell 
      cell.configureCell(UIImage(named: "Talk")!, text: "From Some text \(indexPath.row)") 
      return cell 
     } else { 
      let cell = tableView.dequeueReusableCellWithIdentifier(kToCellIdentifier, forIndexPath: indexPath) as! CustomTableViewCell 
      cell.configureCell(UIImage(named: "Email")!, text: "To Some text \(indexPath.row)") 
      return cell 
     } 
    } 
}