Раздел UITableview - Как правильно пересчитать высоту? - PullRequest
0 голосов
/ 16 января 2019

Видео:

https://youtu.be/sSHrxSIHUM4

Как вы можете видеть на видео, проблема, которую я получил. Ограничение высоты изображения было нарушено, так как на этикетке также отсутствовала высота. Они в разделе таблицы (класс UITableHeaderFooter). Я использовал automaticDimension, чтобы вычислить его высоту, и результат был исправлен.

Это ограничение просмотра изображения. (ограничение высоты по умолчанию равно 184 и будет обновляться во время выполнения, зависит от соотношения.)

https://uphinhnhanh.com/image/SAezyz

И ограничение метки:

https://uphinhnhanh.com/image/SAeT5Y

Проблема возникла после того, как я позвонил table reload, чтобы перенастроить данные вида разреза и высоту, а затем загрузить изображение. Я получил предупреждение о нарушении ограничений. Xcode нарушил ограничение высоты просмотра изображения, которое вызывает проблему.

(
    "<NSLayoutConstraint:0x2807252c0 UIImageView:0x109c002d0.height == 735.885   (active)>",
    "<NSLayoutConstraint:0x280727160 UIImageView:0x109c007f0.height == 40   (active)>",
    "<NSLayoutConstraint:0x280715900 UIView:0x109c00d10.height == 51   (active)>",
    "<NSLayoutConstraint:0x2807140f0 UILayoutGuide:0x281d7e680'UIViewSafeAreaLayoutGuide'.bottom == UIView:0x109c00d10.bottom   (active)>",
    "<NSLayoutConstraint:0x2807174d0 V:|-(11)-[UIImageView:0x109c007f0]   (active, names: '|':engie_up.PostDetailHeaderView:0x109c00000 )>",
    "<NSLayoutConstraint:0x280717c50 V:[UIImageView:0x109c007f0]-(18.5)-[engie_up.KwExpandableContextLabel:0x10491c600'bfbfnff']   (active)>",
    "<NSLayoutConstraint:0x280715130 V:[engie_up.KwExpandableContextLabel:0x10491c600'bfbfnff']-(18)-[UIImageView:0x109c002d0]   (active)>",
    "<NSLayoutConstraint:0x280714fa0 V:[UIImageView:0x109c002d0]-(0)-[UIView:0x109c00d10]   (active)>",
    "<NSLayoutConstraint:0x28072ad00 'UIView-Encapsulated-Layout-Height' engie_up.PostDetailHeaderView:0x109c00000.height == 343   (active)>",
    "<NSLayoutConstraint:0x2807179d0 'UIViewSafeAreaLayoutGuide-bottom' V:[UILayoutGuide:0x281d7e680'UIViewSafeAreaLayoutGuide']-(0)-|   (active, names: '|':engie_up.PostDetailHeaderView:0x109c00000 )>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x2807252c0 UIImageView:0x109c002d0.height == 735.885   (active)>

Я заметил, что 'UIView-Encapsulated-Layout-Height' является оценочной высотой.

Код извлечения прост, поскольку я использую Kingfisher

let ratio = CGFloat(image.width) / CGFloat(image.height)
userContentImageViewHeightConstraint.constant = CGFloat((UIScreen.main.bounds.width) / ratio)
self.userContentImageView.kf.indicatorType = .activity
self.userContentImageView.kf.setImage(with: URL(string: image.url), completionHandler: { (_, _, _, _) in
     self.setNeedsLayout()
     self.layoutIfNeeded()
     })

Итак, я хочу спросить, как я могу исправить нарушение ограничения правильно?

Спасибо.

Ответы [ 2 ]

0 голосов
/ 16 января 2019

Я снова проверил ваши скриншоты.Все выглядит хорошо для меня.Теперь я все еще догадываюсь здесь.Обычно, когда возникает предупреждение о таких ограничениях, даже если это занимает мое время, я решаю это.Хорошо, что у вас уже есть размер изображения данных.

Из этого блока кода:

self.userContentImageView.kf.setImage(with: URL(string: image.url), completionHandler: { (_, _, _, _) in
     self.setNeedsLayout()
     self.layoutIfNeeded()
     })

Это ужасно и определенно приведет к появлению мерцающей или нежелательной ошибки анимации / движения, как в вашемдемонстрация видео.

Обычно для меня достаточно self.layoutIfNeeded(), чтобы настроить макет ПОСЛЕ настройки ограничения любого вида.

Таким образом, ваш блок кода может быть преобразован в следующее:

let ratio = CGFloat(image.width) / CGFloat(image.height)
userContentImageViewHeightConstraint.constant = CGFloat((UIScreen.main.bounds.width) / ratio)
self.layoutIfNeeded()
self.userContentImageView.kf.indicatorType = .activity
self.userContentImageView.kf.setImage(with: URL(string: image.url), completionHandler: { (_, _, _, _) in })

ИЛИ ЛУЧШЕ, (я понял, что это внутри вашей ячейки):

Прежде чем вы вернете свою ячейку в cellForRow, вы выполните настройку ограничений!Раньше у меня был личный проект с тем же потоком / логикой, что и у вас - случайные размеры изображений с сетевыми вызовами.

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        self.feedCell = tableView.dequeueReusableCell(withIdentifier: self.feedCell.identifier)
            as! FeedTableViewCell
        self.feedCell.indexPath = indexPath
        self.feedCell.delegate = self

        let post = self.catPosts[indexPath.row]
        self.feedCell.post = post

        let aspectRatio = self.feedCell.getAspectRatioAccordingToiPhones(cellImageFrame: self.feedCell.frame.size, media: post.media!.first!)
        self.feedCell.constraint_PostHeight?.update(offset: aspectRatio)

        return self.feedCell
    }

и внутри моей камеры у меня есть метод getAspectRadio....:

func getAspectRatioAccordingToiPhones(cellImageFrame: CGSize, media: Media) -> CGFloat {

        guard let widthNumber = NumberFormatter().number(from: catMedia.width!),
            let heightNumber = NumberFormatter().number(from: catMedia.height!) else {
            return UIScreen.main.bounds.width
        }

        let imageWidth = CGFloat(truncating: widthNumber)
        let imageHeight = CGFloat(truncating: heightNumber)

        let widthOffset = imageWidth - cellImageFrame.width
        let widthOffsetPercentage = (widthOffset * 100) / imageWidth
        let heightOffset = (widthOffsetPercentage * imageHeight) / 100
        let effectiveHeight = imageHeight - heightOffset
        return effectiveHeight
    }

Надеюсь, это поможет тебе сейчас :) Удачи!

0 голосов
/ 16 января 2019

Обновление: я удалил ограничение высоты изображения и добавил ограничение соотношения сторон, разрыв теперь исчез, но получил тот же результат в видео

        let ratio = CGFloat(image.width) / CGFloat(image.height)
        let constraint = NSLayoutConstraint(item: self.userContentImageView,
                                            attribute: NSLayoutConstraint.Attribute.width,
                                            relatedBy: NSLayoutConstraint.Relation.equal,
                                            toItem: self.userContentImageView,
                                            attribute: NSLayoutConstraint.Attribute.height,
                                            multiplier: ratio,
                                            constant: 0.0)
        constraint.priority = 999
        self.userContentImageViewAspectConstraint = constraint

Обновление 2: 18 января 2019

Наконец-то я нашел основную причину проблемы. Я не заметил, что нижнее ограничение нижнего вида совмещено с макетом безопасной области. Это приводит к тому, что вначале вид поднимается над панелью вкладок, и это создает дополнительное пространство и нарушает высоту ограничения изображения (его приоритет - 999). Я изменил выравнивание на супер-вид, а затем проблема исчезла.

...