uicollectionviewlayout - Remove Oscillation from UIAttachmentBehavior in UICollectionView -
i attempting recreate spring behavior see in ios messages app in uicollectionview
. messages have various cell sizes based on text size. have created custom uicollectionviewflowlayout
add behavior uicollectionview
message bubbles continue oscillate after user has stopped scrolling. have tried number of combinations in length
, damping
, spring
values oscillation never goes away.
after reading of other stack questions did find comment
in order prevent oscillation it's necessary dynamically increase damping factor on quadratic scale attached views closer , closer attachment points. <
but not sure started implementing on have. or guidance appreciated.
below code on uicollectionviewflowlayout
creating current effect.
- (void) preparelayout { [super preparelayout]; cgrect originalrect = (cgrect){.origin = self.collectionview.bounds.origin, .size = self.collectionview.frame.size}; cgrect visiblerect = cgrectinset(originalrect, -50, -50); nsarray *itemsinvisiblerectarray = [super layoutattributesforelementsinrect:visiblerect]; nsset *itemsindexpathsinvisiblerectset = [nsset setwitharray:[itemsinvisiblerectarray valueforkey:@"indexpath"]]; nspredicate *predicate = [nspredicate predicatewithblock:^bool(uiattachmentbehavior *behaviour, nsdictionary *bindings) { bool currentlyvisible = [itemsindexpathsinvisiblerectset member:[[[behaviour items] firstobject] indexpath]] != nil; return !currentlyvisible; }]; nsarray *nolongervisiblebehaviours = [self.animator.behaviors filteredarrayusingpredicate:predicate]; [nolongervisiblebehaviours enumerateobjectsusingblock:^(id obj, nsuinteger index, bool *stop) { [self.animator removebehavior:obj]; [self.visibleindexpathsset removeobject:[[[obj items] firstobject] indexpath]]; }]; nspredicate *newpredicate = [nspredicate predicatewithblock:^bool(uicollectionviewlayoutattributes *item, nsdictionary *bindings) { bool currentlyvisible = [self.visibleindexpathsset member:item.indexpath] != nil; return !currentlyvisible; }]; nsarray *newlyvisibleitems = [itemsinvisiblerectarray filteredarrayusingpredicate:newpredicate]; cgpoint touchlocation = [self.collectionview.pangesturerecognizer locationinview:self.collectionview]; [newlyvisibleitems enumerateobjectsusingblock:^(uicollectionviewlayoutattributes *item, nsuinteger idx, bool *stop) { cgpoint center = item.center; uiattachmentbehavior *springbehaviour = [[uiattachmentbehavior alloc] initwithitem:item attachedtoanchor:center]; springbehaviour.length = 0.1f; springbehaviour.damping = 3.0f; springbehaviour.frequency = 2.8f; if (!cgpointequaltopoint(cgpointzero, touchlocation)) { cgfloat ydistancefromtouch = fabs(touchlocation.y - springbehaviour.anchorpoint.y); cgfloat xdistancefromtouch = fabs(touchlocation.x - springbehaviour.anchorpoint.x); cgfloat scrollresistance = (ydistancefromtouch + xdistancefromtouch) / 1500.0f; if (self.latestdelta < 0) { center.y += max(self.latestdelta, self.latestdelta*scrollresistance); } else { center.y += min(self.latestdelta, self.latestdelta*scrollresistance); } item.center = center; } [self.animator addbehavior:springbehaviour]; [self.visibleindexpathsset addobject:item.indexpath]; }]; }
you can fix 2 steps.
1. add action behavior when initials make sure center of cell doesn't change during animation
springbehaviour.action = ^{ cgpoint itemcenter = item.center; itemcenter.x = center.x; item.center = itemcenter; };
- remove/re-add behaviors when collectionview stops scrolling. this, need implement scrollview delegate method , in method remove/re-add behaviors.
- (void)scrollviewdidenddecelerating:(uiscrollview *)scrollview { zzhcollectionflowlayout *flowlayout = self.collectionview.collectionviewlayout; if ([flowlayout iskindofclass:[zzhcollectionflowlayout class]]) { [flowlayout removeanimationbehavior]; } else { // nsassertionhandler } } - (void)removeanimationbehavior { nsarray *behaviors = self.dynamicanimator.behaviors; [self.dynamicanimator removeallbehaviors]; (uidynamicbehavior *obj in behaviors) { [self.dynamicanimator addbehavior:obj]; } }
btw, if there way of changing damping fix, hear it!
Comments
Post a Comment