我在水平UICollectionView
中尝试模仿消息app spring动画我在UICollectionViewFlowLayout子类中使用了UIAttachmentBehavior。但问题是,当我水平滚动时,细胞也会垂直和水平移动,不知何故是一个旋转运动!
我遵循了本教程:
implementing a bouncy uicollectionviewlayout with uikitdynamics
并在我的collectionView中使用。我还关注了iOS 7上的WWDC 2013会话217-Exploring Scroll Views,但问题仍然存在! 有谁知道我该怎么解决这个问题?
-(id)initWithCoder:(NSCoder *)aDecoder{
self = [super initWithCoder:aDecoder];
if (self){
_dynamicAnimator = [[UIDynamicAnimator alloc] initWithCollectionViewLayout:self];
}
return self;
}
- (void)prepareLayout{
[super prepareLayout];
CGSize contentSize = [self collectionViewContentSize];
NSArray *items = [super layoutAttributesForElementsInRect:CGRectMake(0, 0, contentSize.width, 500)];
if (items.count != _dynamicAnimator.behaviors.count) {
[_dynamicAnimator removeAllBehaviors];
for (UICollectionViewLayoutAttributes *item in items) {
UIAttachmentBehavior *springBehavior = [[UIAttachmentBehavior alloc] initWithItem:item attachedToAnchor:item.center];
springBehavior.length = 0.f;
springBehavior.damping = 0.5f;
springBehavior.frequency = 0.8f;
[_dynamicAnimator addBehavior:springBehavior];
}
}
}
- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect{
return [_dynamicAnimator itemsInRect:rect];
}
- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath{
return [_dynamicAnimator layoutAttributesForCellAtIndexPath:indexPath];
}
- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds{
CGFloat scrollDelta = newBounds.origin.x - self.collectionView.bounds.origin.x;
CGPoint touchLocation = [self.collectionView.panGestureRecognizer locationInView:self.collectionView];
for (UIAttachmentBehavior *springBehavior in _dynamicAnimator.behaviors) {
CGPoint anchorPoint = springBehavior.anchorPoint;
CGFloat touchDistance = fabsf(touchLocation.x - anchorPoint.x);
CGFloat resistanceFactor = 0.002;
UICollectionViewLayoutAttributes *attributes = springBehavior.items.firstObject;
CGPoint center = attributes.center;
float resistedScroll = scrollDelta * touchDistance * resistanceFactor;
float simpleScroll = scrollDelta;
float actualScroll = MIN(abs(simpleScroll), abs(resistedScroll));
if(simpleScroll < 0){
actualScroll *= -1;
}
center.x += actualScroll;
attributes.center = center;
[_dynamicAnimator updateItemUsingCurrentState:attributes];
}
return NO;
}
答案 0 :(得分:3)
我的应用中遇到了同样的问题。问题是这一行:
UIAttachmentBehavior *springBehavior = [[UIAttachmentBehavior alloc] initWithItem:item attachedToAnchor:item.center];
问题是项目的中心返回带小数的浮点数。 iOS然后将它们舍入为具有0位小数的浮点数,导致锚点不能很好地居中,因此项目会反弹。
解决方案是确保物品的框架在锚定之前可以被高度和宽度整除2。然后验证item.center是否返回没有小数的浮点数的X和Y值,并且动画可以正常工作。
注意:即使在iOS7中工作也很完美我看到iOS8中的问题与此问题类似,但此解决方案不起作用。
答案 1 :(得分:0)
我在iOS 8中看到完全相同的问题 - 似乎虽然UICollisionBehavior允许创建边界,但UIAttachmentBehavior也不存在(尽管类文档为UIAttachmentBehavior提及了它)。我认为短期解决方案可能只是转移到UIDynamicItemBehavior,这看起来更灵活。有兴趣知道从iOS 7到iOS 8的变化。
答案 2 :(得分:0)
我有这个问题 - iOS8。
现在它已经消失了,感谢这篇文章。
我将补充视图添加到已经使UIDynamics运行良好的UICollectionView中。然后我添加了一些基于常规单元框架的补充视图。计算将返回高度的浮点数(不是0小数)。我想Pauls说,iOS然后必须进行一些舍入,现在创建一个我不想要的y-delta。这就是引发摆动运动的原因 通过舍入我的optionalView高度,问题就消失了。我得到7.5的一致中心,所以我的高度不能被2整除,但它仍在工作。
这里我的补充视图现在是如何计算的
UICollectionViewLayoutAttributes *attributes = [self.dynamicAnimator layoutAttributesForCellAtIndexPath:indexPath];
// put supp view at beginning of cell
// round off height or wierd oscillations will begin as iOS must round also
CGRect suppViewFrame = CGRectMake(attributes.frame.origin.x - 44.0 / 2,
attributes.frame.origin.y - 44.0,
44.0,
roundf(44.0 + attributes.frame.size.height / 2));
我添加的所有内容都是CGRect计算高度部分的roundf
瞧 - 它正在发挥作用。
希望这有助于某人 - 快乐编码