TextureGroup / Texture

Smooth asynchronous user interfaces for iOS apps.
https://texturegroup.org/
Other
8.03k stars 1.3k forks source link

[ASCollectionView] Use UICollectionViewLayout invalidation events to relayout #105

Open garrettmoon opened 7 years ago

garrettmoon commented 7 years ago

From @levi on September 28, 2015 16:39

Issue #690 brought up a good point I've been thinking about as I was putting together the supplementary view architecture briefly this weekend. The current data controller integration with ASCollectionView reiles upon layout invalidation from reloading/inserting/deleting/moving items or @nguyenhuy's new relayout items based upon the collection view's bounds changes. These behaviors closely model the specific implementation of a table view, but it's clear as we have begun to mature the behavior of our collection view most of the sizing events and values (namely constrainedSizeForNode:) have been built around the powerful Collection view layouts.

I've been doing a bit of research into the invalidateLayout and invaldateLayoutWithContext: methods. While the provided context is not as granular as I initially hoped, I believe these events are great candidates for us to use as hooks for relayout events in the collection view's data controller.

Moreover, as we query the collection view for constrained sizes I think we should start asking the collection view layout for specific values. This will move the layout (constrainedSizeForNode:) code we currently have in ASCollectionView into a separate place that is specific to the current collection view layout.

With that, a couple of solutions have come to mind:

  1. Make ASDataController an abstract class that table view and collection view have concrete implementations of. This will give each view the ability to add custom behavior such as supplementary views for collection views and header/footer nodes for tables views.
  2. Once that we have a concrete ASCollectionDataController with supplementary view support, the data controller interfaces with a strategy object that provides all the necessary answers to questions from the data controller about the current layout. For example, "how many supplementary views are in this section?", "what's the constrained size for this node?". This strategy is provided by the client of ASCollectionView and either set directly as a property on ASCollectionDataController or is composed in ASViewController and its values returned at specific points of the data controllers data source method (I'm leaning toward the latter). The default limitation would be a generic strategy for flow layouts.
  3. We migrate ASCollectionView to start node invalidation and relayout on ‘invalidateLayout‘ events. I already have the proxying of invalidateLayout working in a branch, but it's beyond the scope of implementing supplementary views into ASCollectionView. This will allow us to support ‘itemSize‘ changes in a flow layout, for example, and respect the layout invalidation events that can at times use animation transitions to change the item's sizes.

    1 and #2 is where I'm planning to go this week to get my branch building and running. I feel that it should be a flexible enough solution to test and also to continue composing as custom layout authors investigate using their layouts with supplementary views. #3 is where I'd like to start discussion, as it's a little more involved and not something I'm planning to do this week.

Wrote this on my phone, so let me know if anything doesn't make sense.

Copied from original issue: facebookarchive/AsyncDisplayKit#691

garrettmoon commented 7 years ago

From @appleguy on November 11, 2015 4:24

@levi has any aspect of this been implemented? Is this entirely to allow repositioning elements by driving the UICollectionVIewLayout, or are there other benefits?

garrettmoon commented 7 years ago

From @levi on November 13, 2015 0:52

Nothing implemented yet. I would like to eventually add this, as most of the layout invalidation we do is conformed to the behaviors of a table view. The beauty of collection views is that their layout is managed by the layout object and its invalidateLayout method is called every time there needs to be a change in the layout of the inner items. Right now reloadData and layoutSubviews manually calls into the ASDataController to relayout the sizes of the collection view nodes. These two methods actually call invalidateLayout and I'm thinking that proxying it could be the single place to notify the data source for the need to relayout the inner nodes.

Definitely a nice to have that's not super important for most collection view uses, but something I want to do in the next couple of months so ASCollectionView is closer in behavior to its underlying UICollectionView.