2016-11-18 4 views
9

Проблема ячейки выглядит следующим образом: http://i.imgur.com/5iaAiGQ.mp4 (красный цвет из cell.contentView)UICollectionViewCell - содержимое не анимировать вместе contentView

Вот код: https://github.com/nezhyborets/UICollectionViewContentsAnimationProblem

Текущий статус: Содержимое содержимого UICollectionViewCell не изменяется вместе с изменением кадрового содержимого. Он получает размер сразу без анимации.

Другие вопросы столкнулись при выполнении задачи: contentView не анимировать наряду с изменением кадра клетки либо, пока я не сделал это в UICollectionViewCell подкласса:

override func awakeFromNib() { 
    super.awakeFromNib() 

    //Because contentView won't animate along with cell 
    contentView.frame = bounds 
    contentView.autoresizingMask = [.flexibleHeight, .flexibleWidth] 
} 

Другие ноты: Вот код, связанный с анимацией размера ячейки

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { 
    self.selectedIndex = indexPath.row 

    collectionView.performBatchUpdates({ 
     collectionView.reloadData() 
    }, completion: nil) 
} 

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { 
    let isSelected = self.selectedIndex == indexPath.row 
    let someSize : CGFloat = 90 //doesn't matter 
    let sizeK : CGFloat = isSelected ? 0.9 : 0.65 
    let size = CGSize(width: someSize * sizeK, height: someSize * sizeK) 

    return size 
} 

Я получаю те же результаты при использовании collectionView.setCollectionViewLayout(newLayout, animated: true), и нет никакой анимации при использовании collectionView.collectionViewLayout.invalidateLayout() вместо reloadData() inside batchUpdates.

UPDATE При печати imageView.constraints внутри willDisplayCell метода UICollectionView, он печатает пустой массив.

func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) { 
    for view in cell.contentView.subviews { 
     print(view.constraints) 
    } 

    //Outputs 
    //View: <UIImageView: 0x7fe26460e810; frame = (0 0; 50 50); autoresize = RM+BM; userInteractionEnabled = NO; layer = <CALayer: 0x608000037280>> 
    //View constraints: [] 
} 

ответ

13

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

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

  1. Когда клетки выбора или отмены выбора, скажите вид коллекции объект макета, размеры ячеек изменились, и оживить эти изменения в той мере, он может сделать это.Самый простой способ сделать это является использование performBatchUpdates, что создаст новые размеры для быть извлечены из sizeForItemAt, а затем применить новый макет атрибуты для соответствующих ячеек в пределах своего собственной анимации блока:

    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { 
        self.selectedIndex = indexPath.row 
        collectionView.performBatchUpdates(nil) 
    } 
    
  2. Расскажите свои клетки макет их подвиды каждый раз, когда представление коллекции объект макета изменяет атрибуты их расположение (что будет происходить в пределах блока performBatchUpdates анимации):

    // ProblematicCollectionViewCell.swift 
    
    override func apply(_ layoutAttributes: UICollectionViewLayoutAttributes) { 
        super.apply(layoutAttributes) 
        layoutIfNeeded() 
    } 
    

Если вы хотите шой ater, вы можете вставить вызов в performBatchUpdates внутри вызова одного из методов анимации на основе блоков UIView.animate. Длительность анимации по умолчанию для ячеек просмотра коллекции в iOS 10 составляет 0,25.

+0

Для справки, когда 'executeBatchUpdates (nil)' вызывается в представлении коллекции с использованием UICollectionViewFlowLayout, контекст, переданный 'invalidateLayout (с:)', настроен с 'invalidateEverything' и' invalidateDataSourceCounts 'to' false', но 'invalidateFlowLayoutAttributes' и' invalidateFlowLayoutDelegateMetrics' установлены на 'true'. Эффект заключается в том, что объект компоновки потока запрашивает информацию о новом размере и пересматривает положение и размер элементов и представлений, не делая ничего недействительным. – jamesk

1

Вы можете применить transform к клетке, хотя она имеет некоторые недостатки, такие как обработка изменения ориентации.

Для дополнительного воздействия, я добавил изменение цвета и пружинный эффект в смеси, ни один из которых может быть достигнут с помощью перегрузочного маршрута:

func collectionView(_ collectionView: UICollectionView, 
         didSelectItemAt indexPath: IndexPath) { 
     UIView.animate(
      withDuration: 0.4, 
      delay: 0, 
      usingSpringWithDamping: 0.4, 
      initialSpringVelocity: 0, 
      options: UIViewAnimationOptions.beginFromCurrentState, 
      animations: { 
       if(self.selectedIndexPath.row != NSNotFound) { 
        if let c0 = 
         collectionView.cellForItem(at: self.selectedIndexPath) 
        { 
         c0.contentView.layer.transform = CATransform3DIdentity 
         c0.contentView.backgroundColor = UIColor.lightGray 
        } 
       } 
       self.selectedIndexPath = indexPath 
       if let c1 = collectionView.cellForItem(at: indexPath) 
       { 
        c1.contentView.layer.transform = 
         CATransform3DMakeScale(1.25, 1.25, 1) 
        c1.contentView.backgroundColor = UIColor.red 
       } 

      }, 
      completion: nil) 
    } 
+0

Спасибо за подробное объяснение, но ваш вариант не будет удовлетворять дизайнера, и поэтому клиент –

+0

Просто уточнить - я имел в виду расстояние между ячейками. В вашем решении вы увеличили его, так что, когда какая-то ячейка растет в размерах, она подходит к макету. Но это немного взломанно и выглядит слишком хаки –

3

Решение очень просто. Во-первых, в ViewController.collectionView (_, didSelectItemAt :), писать только это:

collectionView.performBatchUpdates({ 
     self.selectedIndex = indexPath.row 
    }, completion: nil) 

А потом, в классе ProblematicCollectionViewCell добавить FUNC:

override func apply(_ layoutAttributes: UICollectionViewLayoutAttributes) { 
    super.apply(layoutAttributes) 

    self.layoutIfNeeded() 
} 

Enjoy!

+0

спасибо, это работает, но Джеймс был первым, кто дал правильный ответ –

Смежные вопросы