problem
i'd make uicollectionview animated scroll specific item.
this works of time, item i'm trying scroll doesn't end being shown.
code
- (void)onclick { // (possibly recompute _items array.) nsinteger target_idx = // (...some valid index of _items) nsindexpath *item_idx = [nsindexpath indexpathforitem:target_idx insection:0]; [self scrolltoitem:item_idx]; } - (void)scrolltoitem:(nsindexpath*)item_idx { // make sure our view up-to-date data want show. nsinteger num_items = [self.collection_view numberofitemsinsection:0]; if (num_items != _items.count) { [self.collection_view reloaddata]; } [self.collection_view scrolltoitematindexpath:item_idx atscrollposition:uicollectionviewscrollpositioncenteredhorizontally animated:yes]; } details
self.collection_viewuicollectionview consists of single row of items, standard flow layout , horizontal scrolling enabled.- i need call
reloaddatabefore scrolling, because it's possible_itemshas changed since uicollectionview last displayed it. - the problem happens animated scrolling; if pass
animated:noworks expected. - when problem happens, post-scroll call
indexpathsforvisibleitemsreveals uicollectionview doesn't think target item visible.
any ideas why scrolling item silently fails sometimes?
update: problem seems come reloading , scrolling in quick succession; if there no reload, scrolling behaves expected. there idioms scrolling item after loading new data?
i've run in similar / same issue after adding item uicollectionview.
what's happening
the issue seems following [collectionview reloaddata] or [collectionview insertitemsatindexpaths: @[newitemindexpath]], the collection view's content size not yet updated.
if try scroll added item visible, fail because the content rect doesn't yet include space new item.
a fix
there simple , robust work around, post scroll event on next iteration of run loop this:
const nsuinteger newindex = [self collectionview: self.collectionview numberofitemsinsection: 0] - 1; nsindexpath *const newpath = [nsindexpath indexpathforitem: newindex insection: 0]; [self.collectionview insertitemsatindexpaths: @[newpath]]; uicollectionviewlayoutattributes *const layoutattributes = [self.collectionview layoutattributesforitematindexpath: newpath]; dispatch_async(dispatch_get_main_queue(), ^{ [self.collectionview scrollrecttovisible: layoutattributes.frame animated: yes]; }); isn't there nicer fix?
while works, "post scroll call on next run loop tick" shenanigans feels hacky.
it preferable if uicollectionview invoke callback when finished updating content rect. uikit has callbacks of style other methods perform asynchronous updates model. example, completion block uiviewcontroller transitions , uiview animations.
uicollectionview not provide callback. far know, there no other simple clean way find when completes update. next run loop tick proxy callback want.
anything else know?
it's useful know uitableview has issue. similar workaround should work there too.
Comments
Post a Comment