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;         }; 
  1. 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

Popular posts from this blog

python - pip install -U PySide error -

arrays - C++ error: a brace-enclosed initializer is not allowed here before ‘{’ token -

cytoscape.js - How to add nodes to Dagre layout with Cytoscape -