35

I am trying to achieve the following effect:

A UICollectionView displays a grid of cells for a parent type of object, e. g. a photo album. When I tap one of these items, I would like to scroll that element to the top of the screen and open a Springboard like folder from it. Inside that folders area, another collection should be shown, consisting of the detail items, i. e. the individual photos of that album. Tapping in the remaining "parent" view closes the folder again. See this schema:

enter image description here

What I have done so far is a regular collection view for the albums. When I select one, it scrolls to selected item to the top and then uses JWFolders to open an empty folder at that place. Once that is shown, I trigger the surrounding UINavigationController to push my 2nd view controller with the detail items. That one is layed out so it appears to the user as if it were still the same view.

There are several problems with this approach, and I would like to know how to do this better:

  1. JWFolders takes a screenshot and animated two halves of it up/downwards to achieve the opening effect. This is ok, but pretty slow on an iPad3, because it moves a lot of pixels and the iPad3's GPU is not quite up to the task.

  2. The 2nd view needs to be pixel-perfect to match on top of the first one. This is likely to break accidentally.

  3. I am limited as to what animations are possible for the view controller transition. The default UINavigationController's push from the right is not fitting. I override that to do a cross-dissolve, but still it is far from ideal.

I would like to get pointers as to how to approach this problem in a maintainable manner that does not require to much creative hacking against what the frameworks are designed to do. I might be missing something obvious here, so pointers to examples or general advice are appreciated.

Update:

I changed the approach a bit. Now I use a container view controller that has two embedded collection view controllers. One for the "Album" and one for the "Photos" part at the bottom. Using a UIImageView in the middle between the two I can get the triangle pointing upward done. This is also nice from a maintenance point of view, because it makes maintenance easier with the two collections being handled completely separately.

The app uses Auto Layout, so I can change the amount of space each of the two embedded views takes by modifying the constraints. This is way faster than the screenshot based approach with JWFolders and works nicely on an iPad3 as well.

This almost gets me where I want to be. The one thing that remains is to get the opening animation right. I would like to simultaneously scroll the Albums collection, so that the tapped item goes to the top and expand the photos collection with the triangle pointing at the Album cell.

Can I somehow "connect" the lower view to that cell via layout constraints, so that the scrollToItemAtIndexPath:atScrollPosition:animated: call drags the lower view open?

Prasen
  • 217
  • 1
  • 5
  • 15
Daniel Schneller
  • 13,728
  • 5
  • 43
  • 72
  • What code are you using to animate the opening of your imageViews collection? – AMayes Mar 30 '13 at 13:50
  • Don't have it at hand right now, but it basically is animating an auto-layout constraint for the space between my views lower edge and the superviews bottom from its original value to 0. – Daniel Schneller Mar 31 '13 at 14:54
  • If you are familier with Xcode Instruments you should try time profiling your code. It's possible there are places were you could improve how JWFolders is animating, as the animations its doing should not be that resource intensive. – Andrew Theis Apr 25 '13 at 20:15
  • The problem is that on a retina iPad 3 there is just a tremendous amount of pixels being moved when you take a split screenshot and move each of the halves. This is just a limitation of the hardware (and my unwillingness to start delving into OpenGL for something like this). – Daniel Schneller May 02 '13 at 22:23
  • 1
    Hey, author of `JWFolders` here. I wrote that code a while ago and it surely could use some optimizations, but the main choking point is with `CALayer`'s `-renderInContext:` call, which just can't be optimized. I wish there was a way to generalize this library to avoid taking a screenshot, but unfortunately there is no way to do so. – sudo rm -rf May 05 '13 at 18:51

2 Answers2

1

To get around it I would lose the library and cause iOS to move those display elements around without screenshots or other tricks. On the tap, cause the tapped icon to retain its normal appearance while you dim all the others. Find the contents of the collection view from the top to the end of the line where the tapped icon is. Create two new collection views - one which contains the top half, including your tapped icon and one containing the rest, below. Animate those views apart to make room for the folder view.

The folder view is another UICollectionView that appears in the gap created. In the main view there are either one or three views presented depending on whether the drawer is open or closed. I would probably look at creating a view controller with a collection view, and using view controller containment to manage all three views. You have complete control over how those views are presented, so you could animate top and bottom views up and down simultaneously to reveal the folder view in place, as Springboard does.

When that's all working then you could generalize and start doing things like deciding to make the tapped icon part of the bottom collection with the folder appearing above if the icon was low on the screen.

(I hesitate to answer this because of the large number of upvotes yet no answers, so I may have missed something - but that is how I would begin trying to achieve the Springboard effect.)

Adam Eberbach
  • 12,309
  • 6
  • 62
  • 114
  • Thanks for the (first) answer :) I don't think you missed something. I asked the question because I would have liked to avoid having to juggle several collection views with animations etc. and would have preferred some "simpler" way that could be used in other places, too. But I have come to the conclusion that it is probably the only feasible way, even though it is more work. We are currently going with something similar to your suggestion. – Daniel Schneller May 08 '13 at 08:09
0

To solve this problem in a relatively easy way, you could try to make the folder a simple UICollectionView subclass and then insert that cell when the albums cell is tapped. In the collection views data source you would have to return different size etc. for the folder cell. In the folder you would have to create the folders collection view, avoid making the folder cell the data source of the cell folder collection view tho.

Bensge
  • 145
  • 1
  • 8