Разверните ячейку табличного представления до высоты содержимого

#ios #swift #uitableview #textview #swift5

#iOS #swift #uitableview #textview #swift5

Вопрос:

В моем ViewController есть TableView, и каждая ячейка в TableView имеет TextView, в котором отображаются стихи. Некоторые стихи длинные, а некоторые короткие. Я сделал некоторый код для расширения UITableViewCell при нажатии, чтобы пользователь мог сосредоточиться на чтении только одного стихотворения, а остальные были бы скрыты.

Это мой код:

 @IBOutlet weak var poemasTableView: UITableView!
    var selectedRowIndex = -1

 func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        if indexPath.row == selectedRowIndex {
            return 240 //Expanded
        }
        return 55 //Not expanded
    }

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        if selectedRowIndex == indexPath.row {
            selectedRowIndex = -1
        } else {
            selectedRowIndex = indexPath.row
        }
        tableView.reloadRows(at: [indexPath], with: .automatic)
    }
 

Это работает нормально, однако я хочу сделать что-то еще. При нажатии на ячейку я хочу, чтобы она расширялась, чтобы соответствовать содержимому TextView. Так, например, если стихотворение слишком велико, новая высота должна быть 320, но если она короче, она должна быть 150 и так далее.

Как я мог это сделать?

Комментарии:

1. Во-первых, есть ли причина, по которой вы используете UITextView вместо UILabel ? Во-вторых, вы пробовали поиск? Здесь есть много похожих вопросов и ответов, а также много-много примеров в Интернете.

Ответ №1:

Вы можете рассчитать ограничительную рамку всего стихотворения, используя boundingRectWithSize . А затем вы бы присвоили вычисленную высоту высоте строки.

 func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    if indexPath.row == selectedRowIndex {
        // Expanded
        let poem: String = poems[indexPath.row]
        let size = CGSize(width: poemasTableView.frame.width, height: .greatestFiniteMagnitude)
        let rectangle: CGRect = NSString(string: poem).boundingRect(with: size,
                             options: .usesLineFragmentOrigin,
                             attributes: [.font: UIFont.systemFont(ofSize: 16)],
                             context: nil)
        let maximum_height: CGFloat = 1366
        let rowHeight: CGFloat = min(rectangle.height, maximum_height)
        return rowHeight
    }
    return 55 //Not expanded
}
 

Комментарии:

1. Спасибо за ваш ответ, однако у меня все еще есть проблема. Поскольку я использую firebase и CoreData в своем приложении, вместо poems я бы использовал «arrayPoemas», который имеет тип «Poemas», а не тип String. Таким образом, в строке «let poem: String» появляется ошибка, поскольку она не может преобразовать тип «Poemas» в тип String. И если я сотру эту «:String», это не позволит мне использовать инициализатор «NSString ()». Как я мог это исправить?

2. Я не очень хорошо знаком с Core Data, но я думаю, что это было бы так let poem: String = (arrayPoemas[indexPath.row].value(forKeyPath: "text") as? String) ?? "" , поскольку суммирование text — это поле вашего объекта Poem, которое содержит текст стихотворения.

3. Я пытался использовать код, но есть проблема. Я не знаю, почему, когда я нажимаю UITableViewCell, он расширяет их все до определенной высоты (я думаю, 320), а не до высоты содержимого.

4. Из вашего вопроса я понял, что вам нужна максимальная высота, на случай, если стихотворение действительно длинное. 320 на самом деле несколько маловат, поэтому я обновил код, чтобы указать максимальную высоту 1366. Дайте мне знать, если это сработает.