2017-05-23 7 views
4

초기 테이블로드 후 모든 것이 올바르게 작동합니다. 그러나 새 셀을 삽입하고 빠르게 스크롤하면 크기가 다시 계산되는 일부 셀 (애니메이션)을 볼 수 있습니다. 정말 이상하고 2-3 셀 최대가 발생합니다. 나는 반전 된 셀과 사용자 정의 흐름 레이아웃을 가진 상향식 콜렉션 뷰를 사용하고 있지만 애니메이션도 없습니다. 또한, 키보드 가죽 스크롤, 그래서스크롤하는 동안 UICollectionView 셀의 크기가 재 계산됩니다 (깜박임)

셀 삽입 .. 함께 할 수있는 뭔가가있을 때 문제의

self.collectionView?.insertItems(at: [indexPath]) 

    UIView.performWithoutAnimation { 
     self.collectionView?.reloadItems(at: indexPaths) 
     self.view.layoutIfNeeded() 
    } 
    self.collectionView?.setContentOffset(CGPoint(x: 0, y: 0), animated: true) 

비디오 : 또한

http://vimple.co/3c39cb325b9c4ec19173fea015b6cc8b

override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 

    let newIndex : Int = messagesDataArray.count - 1 - indexPath.item 
    if messagesDataArray[newIndex].otherPerson == true { 
     let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "ConversationCellOtherPerson", for: indexPath) as! ConversationCellOtherPerson 
     cell.data = messagesDataArray[newIndex] 
     cell.personImageView.image = otherPersonImage 
     return cell 
    } else { 
     let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "ConversationCellUser", for: indexPath) as! ConversationCellUser 
     cell.data = messagesDataArray[newIndex] 
     return cell 
    } 

} 

. ConversationCellUser :

class ConversationCellUser : UICollectionViewCell { 

    let messageLabel = ConversationLabel() 
    let mainContainerView = UIView() 
    let textContainerView : UIView = { 
     let view = UIView() 
     view.layer.cornerRadius = 20 
     return view 
    }() 

    var data : MessagesInfo? { didSet { updateCell() } } 


    func updateCell() { 
     guard let data = data else { return } 
     messageLabel.text = data.messageText 
    } 

    override init(frame: CGRect) { 
     super.init(frame: frame) 

     backgroundColor = .clear 
     clipsToBounds = true 

     messageLabel.translatesAutoresizingMaskIntoConstraints = false 
     textContainerView.translatesAutoresizingMaskIntoConstraints = false 
     mainContainerView.translatesAutoresizingMaskIntoConstraints = false 

     mainContainerView.addSubview(textContainerView) 
     textContainerView.addSubview(messageLabel) 
     contentView.addSubview(mainContainerView) 



     NSLayoutConstraint(item: textContainerView, attribute: .right, relatedBy: .equal, toItem: mainContainerView, attribute: .right, multiplier: 1, constant: -10).isActive = true 


     textContainerView.addConstraintsWithFormat(format: "H:|-14-[v0]-14-|", views: messageLabel) 
     textContainerView.addConstraintsWithFormat(format: "V:|-10-[v0]-10-|", views: messageLabel) 

     contentView.addConstraintsWithFormat(format: "H:|[v0]|", views: mainContainerView) 
     contentView.addConstraintsWithFormat(format: "V:|[v0]|", views: mainContainerView) 

     textContainerView.backgroundColor = .lightGray 


    } 

    required init?(coder aDecoder: NSCoder) { 
     fatalError("init(coder:) has not been implemented") 
    } 

    override func apply(_ layoutAttributes: UICollectionViewLayoutAttributes) { 
     super.apply(layoutAttributes) 
     transform = CGAffineTransform(a: 1, b: 0, c: 0, d: -1, tx: 0, ty: 0) 
     updateConstraints() 
     setNeedsUpdateConstraints() 

    } 
} 

ConversationLabel :

class ConversationLabel : BaseMessageLabel { 

    override init(frame: CGRect) { 
     super.init(frame: frame) 

     self.textColor = .white 
     self.font = UIFont(name: "AvenirNext-Medium", size: 14) 
     self.lineBreakMode = .byWordWrapping 
     self.numberOfLines = 0 

     self.preferredMaxLayoutWidth = 200 
    } 

    required init?(coder aDecoder: NSCoder) { 
     fatalError("init(coder:) has not been implemented") 
    } 
} 

SizeForItem :

Github - jochenschoellig - ChatCollectionViewFlowLayout

:

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { 

    var height : CGFloat = 80 

    let text = messagesDataArray[indexPath.row].messageText 

    height = estimateFrameFor(text).height + 20 

    return CGSize(width: collectionView.bounds.size.width, height: height) 


} 

private func estimateFrameFor(_ text : String) -> CGRect { 
    let size = CGSize(width: 200, height: 1000) 
    return NSString(string: text).boundingRect(with: size, options: .usesLineFragmentOrigin, attributes: [NSFontAttributeName : UIFont(name: "AvenirNext-Medium", size: 14)!], context: nil) 
} 

그리고 내가 사용하고있어 FlowLayout의이입니다 안녕하세요, 문제가있는 작은 프로젝트를 만들었습니다. Github - testLP

+2

귀하의 cellForRowAtIndexPath에 대한 코드를 공유하십시오. – KKRocks

답변

1

담당자가 충분하지 않습니다. 그러나 주석이 달린대로 ConversationLabel 클래스, sizeForItemAtIndexPath 재정의 코드 및 사용자 정의 FlowLayout 클래스에 대한 코드를 제공해주십시오. 사용자 정의 레이아웃 클래스를 추가하면 결과 동작을 간과하기 쉽습니다.

주어진 방법이 없으면 여기에서 운이별로 없을 것입니다. 그렇게하면 내 대답을보고 업데이트 할 것입니다.

그러나 비디오에서 판단, 여기에 내가 먼저보고 싶은데 무엇 : 세포가 자신의 색인이 표시 될 때, 애니메이션이라고 할 수있는 collectionview의 보이는 부분에 다시 추가되기 때문에

크기를 적용하는 데 사용하는 셀 요소가 충분히 빠르게 업데이트되지 않으면 지연 될 수있는 sizeForItemAtIndexPath 내부에 적용한 크기 조정 때문입니다. 또는 셀 뷰를 볼 때마다 호출 제약 조건 리셋기를 수행하므로 지연으로 인해 애니메이션이 어떻게 든 보일 수 있습니다 (이는 장치에 따라 지연이 발생할 수 있음). apply(_ layoutAttributes: UICollectionViewLayoutAttributes) 무시 때문에 후자를 제안합니다. 문서 here이 제공된 경우 : updateConstraints()을 한 번 호출 한 다음 바로 뒤에 setNeedsUpdateConstraints()을 호출합니다. 그러면 updateConstraints()이 표시 될 때 셀보기의 레이아웃을 호출합니다 (애니메이션을 볼 때). 따라서 여기에서 두 번 작업을하고 있습니다. 애니메이션 대기열에 추가 할 수 있습니다. 또는 변형 속성을 재설정하기 때문에 고려하지 않은 추가 애니메이션을 예약 할 수도 있습니다. 마지막으로,이 동작이 원인이되는 곳을 암시 할 수 있지만 사용자 정의 FlowLayout 클래스 없이는 말할 수 없습니다.here 언급 한 바와 같이 : 당신의 속성 값을 비교하는 방법 : 당신이 서브 클래스 및 사용자 정의 레이아웃 속성을 구현하는 경우

, 당신은 또한 상속 ISEQUAL를 재정의해야합니다. iOS 7 이상에서 컬렉션보기는 해당 속성이 변경되지 않은 경우 레이아웃 속성을 적용하지 않습니다. 은 이전 과 새 특성 개체를 isEqual : 메서드를 사용하여 비교하여 특성이 변경되었는지 여부를 확인합니다. 이 post about iOS7 and later os builds에서 언급 된 바와 같이

그리고, : 당신이 apply(_ layoutAttributes: UICollectionViewLayoutAttributes) 메소드를 오버라이드 (override) 이후는, 당신은 레이아웃이 원하는 방식으로 특성을 비교하여 자신의 코드로 isEqual(_ object: Any?) method를 오버라이드 (override)로되어있다. ISEQUAL 재정의 example

:

override public func isEqual(_ object: Any?) -> Bool { 
     guard let rhs = object as? DateClass else { 
      return false 
     } 
     let lhs = self 

     return lhs.date1 == rhs.date1 && 
      lhs.date2 == rhs.date2 && 
      lhs.date3 == rhs.date3 
    } 

당신은 당신의 UICollectionViewLayoutAttributes 서브 클래스의 범위 내에서 재정을 가하고, 당신의 UICollectionViewLayoutAttributes와 DateClass을 바꿀 것입니다.

코드에서 알 수 있듯이 특정 메소드를 실수로 호출하는 것처럼 보입니다. 또는 UICollectionViewLayoutAttributes를 올바르게 하위 클래스로 만들지 않았을 수 있습니다. 다시 말하지만, 귀하가 제공하는 것에 대한 최선의 해결책입니다. 누락 된 코드를 추가하면 대답이 업데이트됩니다!

+0

안녕하세요, 답장을 보내 주셔서 감사합니다. 누락 된 코드 조각을 추가했습니다. – HelloimDarius