iOS swift UICollectionView теряет ограничения ячеек после прокрутки мимо первого полного экрана - PullRequest
1 голос
/ 23 октября 2019

Я пытаюсь узнать, как работать с UICollectionViews в приложении Swift для iOS - просто простое приложение, которое отображает изображение и метку в ячейке 25 раз. Изначально плохие ограничения не давали возможности CollectionView отображать что-либо, но как только я разобрался с этим, CollectionView, по-видимому, отображает ячейки так, как нужно и ожидаемо. Отладочные сообщения отображались из моего метода Layout для всех 25 элементов, как и ожидалось.

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

Пример в симуляторе

В коде нет ничего особенного, особенно в макете -вот этот код:

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        if indexPath.item > 10 {
        // Limit number of debug messages
            print("view.bounds: \(view.bounds)")
            print("collectionView.bounds: \(collectionView.bounds)")
            print("collectionView.alignmentRectInsets: \(collectionView.alignmentRectInsets)")
            print("collectionView.contentInset: \(collectionView.contentInset)")
        }
        let width = view.bounds.width
        print("width[\(indexPath.item)]: \(width)")
        let cellDimension = (width / 2 ) - 15
        print("cellDimension[\(indexPath.item)]: \(cellDimension)")
        let returnSize = CGSize(width: cellDimension, height: cellDimension)
        print("returnSize[\(indexPath.item)]: \(returnSize)")
        return returnSize
    }

После того, как он пройдет 11-й пункт, отладчик начинает извергать множество сообщений:

2019-10-22 01:32:54.794032-0500 CollectionTest#1[13173:339022] The behavior of the UICollectionViewFlowLayout is not defined because:
2019-10-22 01:32:54.794203-0500 CollectionTest#1[13173:339022] the item width must be less than the width of the UICollectionView minus the section insets left and right values, minus the content insets left and right values.
2019-10-22 01:32:54.794360-0500 CollectionTest#1[13173:339022] Please check the values returned by the delegate.
2019-10-22 01:32:54.794856-0500 CollectionTest#1[13173:339022] The relevant UICollectionViewFlowLayout instance is <UICollectionViewFlowLayout: 0x7fe4c1407750>, and it is attached to <UICollectionView: 0x7fe492819400; frame = (0 0; 414 736); clipsToBounds = YES; autoresize = LM+W+RM+TM+H+BM; gestureRecognizers = <NSArray: 0x600000965050>; layer = <CALayer: 0x60000076efe0>; contentOffset: {0, 355}; contentSize: {414, 2512}; adjustedContentInset: {20, 0, 0, 0}> collection view layout: <UICollectionViewFlowLayout: 0x7fe4c1407750>.
2019-10-22 01:32:54.801289-0500 CollectionTest#1[13173:339022] Make a symbolic breakpoint at UICollectionViewFlowLayoutBreakForInvalidSizes to catch this in the debugger.
This just goes on and on ... abbreviated for brevity.

Дело в том, что все ячейки были в порядке раньше.

Дополнительный код:

CollectionViewCell.swift


import UIKit


class CollectionViewCell: UICollectionViewCell {
    @IBOutlet weak var cellImage: UIImageView!
    @IBOutlet weak var cellLabel: UILabel!


}


ViewController.swift


import UIKit


class ViewController: UICollectionViewController, UICollectionViewDelegateFlowLayout {


    override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 25
    }


    override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! CollectionViewCell
        cell.cellImage.image = UIImage(named: "file-35")
        cell.cellLabel.text = "cell# \(indexPath.item)"


        cell.layer.borderWidth = 0.5
        cell.layer.borderColor = UIColor.lightGray.cgColor
        cell.layer.cornerRadius = 10


        cell.backgroundColor = UIColor.black
        cell.cellImage.layer.cornerRadius = 10


        print("indexPath.item: \(indexPath.item)")
        print("view.bounds: \(view.bounds)")
        print("collectionView.bounds: \(collectionView.bounds)")
        print("collectionView.contentInset: \(collectionView.contentInset)")
        print("collectionView.alignmentRectInsets: \(collectionView.alignmentRectInsets)")


        print("layoutAttributesForItem: \(String(describing: collectionView.layoutAttributesForItem(at: indexPath)))")


        return cell
    }




    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        collectionView.delegate = self
        collectionView.dataSource = self
//        view.translatesAutoresizingMaskIntoConstraints = true
    }

Кстати, не имеет значения, какая версия симулятора времени выполнения используется.

Любая помощь, указатели, предложения и т. д., очень ценится, пока у меня еще есть волосы, чтобы вытащить. Спасибо.

Ответы [ 2 ]

0 голосов
/ 24 октября 2019

Спасибо за предложения. Я нашел статью о переполнении стека, которая подтолкнула меня в направлении, которое, похоже, помогло решить проблемы.

Я могу ошибаться, но мои наблюдения говорят мне, что, похоже, не все ячейки получают свой размер, инициализированный изРаскадровка значений. Первые дюжины или около того делают, но когда представление сбора начинает повторно использовать / перерабатывать ячейки, оно теряет размер ячейки. Я попытался установить размер ячейки в cellForItemAt (), но это вызывает некоторые действительно серьезные рекурсивные проблемы.

При просмотре с помощью отладчика sizeForItemAt () вызывается только первоначально, а не тогда, когда ячейки начинают использоваться повторно, а когда размер ячейкибыло потеряно, начинают происходить всякие нежелательные вещи.

Инициализация размера ячейки в viewDidLoad () устранила большинство проблем, то есть до тех пор, пока устройство не будет повернуто, тогда sizeForItemAt () вызывается в симуляторах iPhoneдля нового макета, но не в симуляторах iPad.

Решением этой проблемы является проверка типа устройства в viewDidLoad () и вычисление нужного количества ячеек в строке. Простая установка размера ячейки макета не решит полностью проблему, если вы хотите, чтобы при повороте устройства было разное количество ячеек в ряду.

Похоже, что эти проблемы, по крайней мере, укрощены.

Я просто немного обеспокоен тем, что мне чего-то не хватает, потому что функция sizeForItemAt () вызывается не так, как ожидалось.

0 голосов
/ 23 октября 2019

Попробуйте установить свойство clipToBounds для cellImage внутри CollectionViewCell на true, т.е.

class CollectionViewCell: UICollectionViewCell {
    @IBOutlet weak var cellImage: UIImageView!

    override func awakeFromNib() {
        super.awakeFromNib()
        self.cellImage.clipsToBounds = true //here..
    }
    //rest of the code....
}

Вы также можете установить clipToBounds из cellImage в самом пользовательском интерфейсе, т. е.

enter image description here

Примечание: Переместите весь код расположения ячеек в CollectionViewCell вместо записи всего в cellForItemAt. Это сделает код менее громоздким и читабельным.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...