[ASDisplayNode] Add automatic measurement before layout (#1725)

* Add automatic measurement before layout

* Remove code not needed or addressed in a different PR

* Adjust comments and rename __layoutSublayouts to __layoutSubnodes

* Check before setting up a placeholder layer if the node should have a placeholder
This commit is contained in:
Michael Schneider 2016-07-14 21:51:40 -07:00 committed by appleguy
parent a8c5ac138d
commit 359785ac92
4 changed files with 51 additions and 40 deletions

View File

@ -17,6 +17,8 @@
#import <AsyncDisplayKit/ASAsciiArtBoxCreator.h> #import <AsyncDisplayKit/ASAsciiArtBoxCreator.h>
#import <AsyncDisplayKit/ASLayoutable.h> #import <AsyncDisplayKit/ASLayoutable.h>
#define ASDisplayNodeLoggingEnabled 0
@class ASDisplayNode; @class ASDisplayNode;
/** /**

View File

@ -53,8 +53,11 @@ NSString * const ASRenderingEngineDidDisplayNodesScheduledBeforeTimestamp = @"AS
@end @end
//#define LOG(...) NSLog(__VA_ARGS__) #if ASDisplayNodeLoggingEnabled
#define LOG(...) NSLog(__VA_ARGS__)
#else
#define LOG(...) #define LOG(...)
#endif
// Conditionally time these scopes to our debug ivars (only exist in debug/profile builds) // Conditionally time these scopes to our debug ivars (only exist in debug/profile builds)
#if TIME_DISPLAYNODE_OPS #if TIME_DISPLAYNODE_OPS
@ -880,7 +883,7 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c)
- (void)animateLayoutTransition:(id<ASContextTransitioning>)context - (void)animateLayoutTransition:(id<ASContextTransitioning>)context
{ {
[self __layoutSublayouts]; [self __layoutSubnodes];
[context completeTransition:YES]; [context completeTransition:YES];
} }
@ -1114,6 +1117,9 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c)
ASDisplayNodeAssertMainThread(); ASDisplayNodeAssertMainThread();
ASDN::MutexLocker l(_propertyLock); ASDN::MutexLocker l(_propertyLock);
CGRect bounds = self.bounds; CGRect bounds = self.bounds;
[self measureNodeWithBoundsIfNecessary:bounds];
if (CGRectEqualToRect(bounds, CGRectZero)) { if (CGRectEqualToRect(bounds, CGRectZero)) {
// Performing layout on a zero-bounds view often results in frame calculations // Performing layout on a zero-bounds view often results in frame calculations
// with negative sizes after applying margins, which will cause // with negative sizes after applying margins, which will cause
@ -1132,8 +1138,40 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c)
[self layoutDidFinish]; [self layoutDidFinish];
} }
- (void)measureNodeWithBoundsIfNecessary:(CGRect)bounds
{
// Normally measure will be called before layout occurs. If this doesn't happen, nothing is going to call it at all.
// We simply call measureWithSizeRange: using a size range equal to whatever bounds were provided to that element
if (self.supernode == nil && !self.supportsRangeManagedInterfaceState && [self _hasDirtyLayout]) {
if (CGRectEqualToRect(bounds, CGRectZero)) {
LOG(@"Warning: No size given for node before node was trying to layout itself: %@. Please provide a frame for the node.", self);
} else {
[self measureWithSizeRange:ASSizeRangeMake(bounds.size, bounds.size)];
}
}
}
- (void)layout
{
ASDisplayNodeAssertMainThread();
if ([self _hasDirtyLayout]) {
return;
}
[self __layoutSubnodes];
}
- (void)__layoutSubnodes
{
for (ASLayout *subnodeLayout in _layout.sublayouts) {
((ASDisplayNode *)subnodeLayout.layoutableObject).frame = [subnodeLayout frame];
}
}
- (void)layoutDidFinish - (void)layoutDidFinish
{ {
// Hook for subclasses
} }
- (CATransform3D)_transformToAncestor:(ASDisplayNode *)ancestor - (CATransform3D)_transformToAncestor:(ASDisplayNode *)ancestor
@ -2463,24 +2501,6 @@ void recursivelyTriggerDisplayForLayer(CALayer *layer, BOOL shouldBlock)
[layoutTransition startTransition]; [layoutTransition startTransition];
} }
- (void)layout
{
ASDisplayNodeAssertMainThread();
if ([self _hasDirtyLayout]) {
return;
}
[self __layoutSublayouts];
}
- (void)__layoutSublayouts
{
for (ASLayout *subnodeLayout in _layout.sublayouts) {
((ASDisplayNode *)subnodeLayout.layoutableObject).frame = [subnodeLayout frame];
}
}
- (void)displayWillStart - (void)displayWillStart
{ {
ASDisplayNodeAssertMainThread(); ASDisplayNodeAssertMainThread();

View File

@ -14,8 +14,7 @@
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// //
#import <AsyncDisplayKit/AsyncDisplayKit.h> #import <UIKit/UIKit.h>
#import <AsyncDisplayKit/ASVideoNode.h>
@interface ViewController : UIViewController @interface ViewController : UIViewController

View File

@ -16,8 +16,7 @@
// //
#import "ViewController.h" #import "ViewController.h"
#import "ASLayoutSpec.h" #import <AsyncDisplayKit/AsyncDisplayKit.h>
#import "ASStaticLayoutSpec.h"
@interface ViewController()<ASVideoNodeDelegate> @interface ViewController()<ASVideoNodeDelegate>
@property (nonatomic, strong) ASDisplayNode *rootNode; @property (nonatomic, strong) ASDisplayNode *rootNode;
@ -28,12 +27,13 @@
#pragma mark - UIViewController #pragma mark - UIViewController
- (void)viewWillAppear:(BOOL)animated - (void)viewDidLoad
{ {
[super viewWillAppear:animated]; [super viewDidLoad];
// Root node for the view controller // Root node for the view controller
_rootNode = [ASDisplayNode new]; _rootNode = [ASDisplayNode new];
_rootNode.frame = self.view.bounds;
_rootNode.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; _rootNode.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
ASVideoNode *guitarVideoNode = self.guitarVideoNode; ASVideoNode *guitarVideoNode = self.guitarVideoNode;
@ -68,16 +68,6 @@
[self.view addSubnode:_rootNode]; [self.view addSubnode:_rootNode];
} }
- (void)viewDidLayoutSubviews
{
[super viewDidLayoutSubviews];
// After all subviews are layed out we have to measure it and move the root node to the right place
CGSize viewSize = self.view.bounds.size;
[self.rootNode measureWithSizeRange:ASSizeRangeMake(viewSize, viewSize)];
[self.rootNode setNeedsLayout];
}
#pragma mark - Getter / Setter #pragma mark - Getter / Setter
- (ASVideoNode *)guitarVideoNode; - (ASVideoNode *)guitarVideoNode;