facebookarchive / AsyncDisplayKit

Smooth asynchronous user interfaces for iOS apps.
http://asyncdisplaykit.org
Other
13.4k stars 2.2k forks source link

Animated placeholders #156

Closed debug29 closed 9 years ago

debug29 commented 9 years ago

In ASNetworkImageNode, add the possibility to make a fade in downloaded image apparition with a property.

Also with ASDisplayNode placeholder.

Like this for example :

ASNetworkImageNode *theNetworkImageNode = [[ASNetworkImageNode alloc] init];
theNetworkImageNode.placeholderEnabled = YES;
theNetworkImageNode.fadeIn = YES;
secretiverhyme commented 9 years ago

@rnystrom, any thoughts on this one?

rnystrom commented 9 years ago

I love the idea. So a quick fade transition as opposed to how the contents snap in once rendered? We would probably want to make the option work with or without a placeholder, right @secretiverhyme?

secretiverhyme commented 9 years ago

Since placeholders obscure the already-rendered node contents, it would be straightforward to allow animating the placeholders away before removing them. I don't think we should provide nontrivial animations or add animation support to the core asynchronous display system, though. Folks can implement display-completion animations in -didFinishDisplay, either by using Core Animation / pop or by swapping out placeholder nodes (à la Paper's shimmery placeholder text effect).

rnystrom commented 9 years ago

Ah, I see. So not animating in the contents, but animating out the placeholder? Should be really simple :smile:

debug29 commented 9 years ago

Possible to make both, actually in my app, i make a feed with lots of pics. And, for make fading pop of downloaded pics i use asnetworkimagenode delegate and use cabasicanimation on layer of the node. But i found that tricks not really good. It could be better to have this option directly in the node property and animate the pop of the pics inside the node class.

Edit : I'm not skilled enough to code that in the kit.

zdnk commented 9 years ago

i think the developer should be able to customise the transition from placeholder to real content within all nodes

ashikase commented 9 years ago

The current implementation of this feature does not appear to allow for custom placeholder image removal animations as @secretiverhyme suggested might be done in -didFinishDisplay (now -displayDidFinish?).

The placeholder layer (_placeholderLayer) is an internal member and provides no API to access it (though it might be blindly obtained using self.layer.sublayers on the node that owns said layer).

When placeholderFadesOut is true, the placeholder will fade out with a (almost unnoticeable) fixed duration of 0.1. When false, the placeholder layer is immediately removed, leaving no chance for it to be animated.

Have I missed something, or does the current implementation indeed prevent custom animations?

rnystrom commented 9 years ago

@ashikase that's currently the case, yes. For the interim we thought it'd be beneficial to add some type of fade animation so that there is at least the option.

Allowing more advanced, or totally custom, animations has a lot of edge cases that will need to be covered. Exposing the _placeholderLayer entirely is something we want to avoid so that the inner machinery doesn't get out of sync.

We totally want to add custom placeholder animations, but it will involve some core changes. Fading is like a placeholder-placeholder.

ashikase commented 9 years ago

Thank you for the confirmation.

For reference, I'm currently able to achieve custom animations using the technique mentioned here (explained in the "Fading in the Cells" section). Unfortunately, this uses a node instead of the (at that time unavailable) placeholder API, and provides a custom layer for the node by subclassing the internal class _ASDisplayLayer.

secretiverhyme commented 9 years ago

The current placeholder API is designed to be simple and lightweight — its chief out-of-the-box function is making sure that nodes look attractive and don't disrupt your app's appearance if they happen to appear onscreen before they've finished rendering. We're happy to make simple improvements to this API, but for any sort of advanced custom animation, you should be working with nodes directly.

For example, Paper's story strip placeholders have a shimmering effect. This is implemented using placeholder nodes. The story strip is initially populated with cheap but fully-functional placeholder cards (try expanding or shrinking the story strip and you'll see they scale correctly!) that have animated text placeholders. Once the story nodes finish rendering, they're swapped out with the placeholders for a seamless transition.

You should be able to implement this yourself with the current version of AsyncDisplayKit, though it'll be a bit tricky (the APIs for manually enqueueing asynchronous display of a node, hooking into completion of an entire hierarchy's display, etc., are overdue for some love). Making this much simpler is on our radar, though! =]

yxztj commented 9 years ago

Is there an easier way to do this now? I took a look at the ASNetworkImageNode code, still the downloaded image is assigned directly:

if (responseImage != NULL) {
     strongSelf->_imageLoaded = YES;
     strongSelf.image = [UIImage imageWithCGImage:responseImage];
}

We haven't found a point to inject our custom transition animation code. Of course we don't want to write a view to do this instead of using ASNetworkImageNode. Any help would be much appreciated.