iOS UITextView внутри UITableViewCell «читать дальше», как в современном App Store - PullRequest
0 голосов
/ 28 октября 2019

Несколько дней я изо всех сил пытался правильно реализовать такое же поведение «читать дальше», как в iOS App Store (скриншот прилагается).

enter image description here

Я использую AutoLayout в моем проекте. Строки UITableView используют собственную высоту строк: tableView.rowHeight = UITableView.automaticDimension.

Я пробовал много способов, просматривая атрибутные строки UITextView, обрезая их вручную и перезапуская запросы макета. Моя последняя попытка - использовать textView.textContainer.exclusionPaths. Вот код, который я получил до сих пор:

import UIKit

class ReadMoreTextViewCell: UITableViewCell {
    static var mediumFont: UIFont {
        return UIFont.systemFont(ofSize: 16)
    }

    private let textView = UITextView()
       private let button: UIButton = {
           let button = UIButton(type: .custom)
           return button
   }()

   override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
       super.init(style: style, reuseIdentifier: reuseIdentifier)

       setupViews()
       setupConstraints()
   }

   required init?(coder aDecoder: NSCoder) {
       super.init(coder: aDecoder)

       setupViews()
       setupConstraints()
   }

   private func setupViews() {
      textView.isScrollEnabled = false
      textView.textContainer.lineFragmentPadding = 0.0
      textView.textContainerInset = .zero
      textView.backgroundColor = UIColor.clear
      textView.textColor = .black

      textView.textContainer.maximumNumberOfLines = 3
      textView.textContainer.lineBreakMode = .byTruncatingTail

      contentView.addSubview(textView)

      button.setTitle("Read more", for: .normal)
      button.titleLabel?.font = ReadMoreTextViewCell.mediumFont
      button.setTitleColor(UIColor.blue, for: .normal)
      button.addTarget(self, action: #selector(readMoreTapped), for: .touchUpInside)
      button.contentEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: -6, right: 0)
      contentView.addSubview(button)
  }

  private func setupConstraints() {
      textView.translatesAutoresizingMaskIntoConstraints = false
      NSLayoutConstraint.activate([
          textView.leadingAnchor.constraint(equalTo: contentView.layoutMarginsGuide.leadingAnchor),
          textView.topAnchor.constraint(equalTo: contentView.layoutMarginsGuide.topAnchor),
          textView.bottomAnchor.constraint(equalTo: contentView.layoutMarginsGuide.bottomAnchor),
          textView.trailingAnchor.constraint(equalTo: contentView.layoutMarginsGuide.trailingAnchor)
      ])
  }

  override func layoutSubviews() {
      super.layoutSubviews()

      contentView.layoutIfNeeded()

      let buttonFrame = CGRect(x: textView.bounds.width - 80, y: textView.bounds.height - 26, width: 80, height: 26)
      button.frame = buttonFrame

      let buttonPath = UIBezierPath(rect: button.frame)
      textView.textContainer.exclusionPaths = [buttonPath]
  }

  override func prepareForReuse() {
      super.prepareForReuse()
      textView.delegate = .none
      textView.attributedText = .none
  }

  func setup(with text: String) {
      textView.attributedText = text.attributedString(font: UIFont.systemFont(ofSize: 16))
  }

  @objc func readMoreTapped() {

  }
}

Результат как на скриншоте ниже:

enter image description here

после обновления ячеек путем вытягивания из видимой UITableView области: enter image description here

Заключительные замечания, мне нужно использовать UITextView здесь. Если вы решили эту проблему в некоторых своих проектах, пожалуйста, помогите: -)

1 Ответ

1 голос
/ 29 октября 2019

Если вы просто пытаетесь получить правильное размещение «Подробнее», вы можете сделать что-то вроде ниже.
Но это не учитывает следующее:

  1. показывает или скрывает кнопку «Читать далее» в зависимости от длины текста textView. Допустим, есть только 2 строки
  2. Действие для расширения ячейки таблицы при нажатии кнопки.

ВsetupViews, которые я удалил: button.contentEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: -6, right: 0) и добавил button.backgroundColor = .white

Назад к коду, обновите, как вы устанавливаете ограничения для кнопки. Вместо того, чтобы устанавливать их с рамкой, сделайте следующее.

    button.translatesAutoresizingMaskIntoConstraints = false
    NSLayoutConstraint.activate([
        button.lastBaselineAnchor.constraint(equalTo: textView.lastBaselineAnchor),
        button.heightAnchor.constraint(equalToConstant: 20),
        button.widthAnchor.constraint(equalToConstant: 80),
        button.trailingAnchor.constraint(equalTo: contentView.layoutMarginsGuide.trailingAnchor)
    ])

С учетом вышесказанного, я получил это как результат enter image description here

Выше все еще может бытьнемного подправил, но это быстрое решение, которое поможет вам выбрать правильный путь, при условии, что я понял ваш вопрос.

...