2016-11-05 8 views
0

У меня очень простой UICollectionView, встроенный в ViewController.Изменение размера UICollectionViewCell при повороте устройства

UICollectionView использует автоматическую компоновку (определенную в IB), чтобы взять все пространство в ViewController.

My UICollectionViewCell имеют одинаковый размер, и они занимают все пространство UICollectionView, потому что я хочу, чтобы в ViewController отображалась только одна ячейка. UICollectionViewCell отображает только UIImage (который встроен в UIScrollView для масштабирования).

Он отлично работает, за исключением случаев, когда устройство вращается. Там это сообщение об ошибке:

Поведение UICollectionViewFlowLayout не определенно, так как: высота элемента должна быть меньше, чем высота UICollectionView минус раздела вставки верхних и нижних значений, минус вставки содержания сверху и снизу значения. Соответствующий экземпляр UICollectionViewFlowLayout, и он привязан к; animations = {bounds.origin =; bounds.size =; положение =; }; layer =; contentOffset: {0, 0}; contentSize: {4875, 323}> макет коллекции:.

Это довольно ясно, мне нужно изменить размер моего UICollectionViewCell, чтобы он соответствовал новой высоте/ширине. После вращения дисплей UICollectionViewCell с соответствующей высотой/шириной, но с плохой анимацией.

Вот код:

@IBOutlet weak var theCollectionView: UICollectionView! 
@IBOutlet weak var theFlowLayout: UICollectionViewFlowLayout! 
    override func viewDidLoad() { 
    super.viewDidLoad() 

    //theCollectionView.delegate = self 
    theCollectionView.dataSource = self 
    automaticallyAdjustsScrollViewInsets = false 
    theFlowLayout.itemSize = theCollectionView.frame.size 
    theFlowLayout.sectionInset = UIEdgeInsetsMake(0,0,0,0) 
    theFlowLayout.minimumLineSpacing = 0.0 
    theCollectionView.reloadData() 
} 


override func viewWillAppear(_ animated: Bool) { 
    super.viewWillAppear(animated) 
} 

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { 
    super.viewWillTransition(to: size, with: coordinator) 
    print("\(#function) \(view.frame.size)") 
    coordinator.animate(alongsideTransition: nil, completion: { 
     _ in 
     self.theFlowLayout.itemSize = self.theCollectionView.frame.size 
    })   
} 

override func viewWillLayoutSubviews() { 
    super.viewWillLayoutSubviews() 
    print("\(#function) \(view.frame.size)") 
} 

override func viewDidLayoutSubviews() { 
    super.viewDidLayoutSubviews() 
    print("\(#function) \(view.frame.size)") 
} 

Вопрос заключается в том, как и когда выполнять изменения UICollectionViewCell, чтобы избежать предупреждения и получить плавную анимацию?

Когда вращение устройства происходит, можно увидеть следующие: viewWillTransition (чтобы: с :) (375,0, 667.0) viewWillLayoutSubviews() (667.0, 375.0) viewDidLayoutSubviews() (667,0, 375,0)

Ошибка отображается сразу после viewDidLayoutSubviews(). Я попытался вызвать theFlowLayout.invalidateLayout() в viewDidLayoutSubviews(), но это не меняет проблему.

Я прочитал другие подобные вопросы, но я не мог найти мой ответ :-(

Спасибо за вашу помощь,

Себастьен

ответ

0

Я не нашел лучшего решения, но по крайней мере это работает .

Я использую viewWillTransition для вычисления индекса ячейки и для сброса смещения после вращения. Чтобы избежать плохой анимации, я установил альфа-значение в 0 и в начале и еще 1 в конце анимации.

viewWillLayoutSubviews используется для аннулирования макета UICollectionViewFlowLayout и viewDidLayoutSubviews для установки нового размера ячейки.

Возможно, это поможет другим, но если у вас есть лучшее решение, поделитесь им!

@IBOutlet weak var theCollectionView: UICollectionView! { 
    didSet { 
     theCollectionView.backgroundColor = UIColor.black 
     theCollectionView.delegate = self 
     theCollectionView.dataSource = self 
    } 
} 

@IBOutlet weak var theFlowLayout: UICollectionViewFlowLayout! { 
    didSet { 
     theFlowLayout.itemSize = theCollectionView.frame.size 
     theFlowLayout.sectionInset = UIEdgeInsetsMake(0,0,0,0) 
     theFlowLayout.minimumLineSpacing = 0.0 
    } 
} 

var assets:[PHAsset]! 
var startAssetIndex = 0 

override func viewDidLoad() { 
    super.viewDidLoad() 
    view.backgroundColor = UIColor.black 
    automaticallyAdjustsScrollViewInsets = false 
    theCollectionView.reloadData() 
} 


override func viewWillAppear(_ animated: Bool) { 
    super.viewWillAppear(animated) 
    theCollectionView.scrollToItem(at: IndexPath(row:startAssetIndex, section:0), at: .left, animated: true) 
} 


/// Resize the collectionView during device rotation 
/// 
/// - Parameters: 
/// - size: New size of the viewController 
/// - coordinator: coordinator for the animation 
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { 
    super.viewWillTransition(to: size, with: coordinator) 

    // Compute the index of the image/video currently displayed 
    let offset = self.theCollectionView.contentOffset; 
    let index = round(offset.x/self.theCollectionView.bounds.size.width); 

    // hide the collection view to avoid horrible animation during the rotation 
    // animation is horrible due to the offset change 
    theCollectionView.alpha = 0.0 
    coordinator.animate(alongsideTransition: nil, completion: { 
     _ in 
     // display the collectionView during the animation 
     self.theCollectionView.alpha = 1.0 

     // compute the new offset based on the index and the new size 
     let newOffset = CGPoint(x: index * self.theCollectionView.frame.size.width, y: offset.y) 
     self.theCollectionView.setContentOffset(newOffset, animated: false) 
    }) 
} 


/// Invalidate the layout of the FlowLayout, it's mandatory for the rotation 
override func viewWillLayoutSubviews() { 
    theFlowLayout.invalidateLayout() 
    super.viewWillLayoutSubviews() 
} 


/// Set the size of the items (mandatory for the rotation) 
override func viewDidLayoutSubviews() { 
    super.viewDidLayoutSubviews() 
    theFlowLayout.itemSize = theCollectionView.frame.size 
} 
Смежные вопросы