diff --git a/_docs/cell-node.md b/_docs/cell-node.md index 6faa4a08..07d09c6d 100755 --- a/_docs/cell-node.md +++ b/_docs/cell-node.md @@ -5,9 +5,138 @@ permalink: /docs/cell-node.html next: text-cell-node.html --- -ASCellNode is maybe the most commonly subclassed node. It can be used as the cell for both ASTableNodes and ASCollectionNodes. +ASCellNode, as you may have guessed, is the cell class of ASDK. Unlike the various cells in UIKit, ASCellNode can be used with ASTableNodes, ASCollectionNodes and ASPagerNodes, making it incredibly flexible. -That being said, subclassing it is largely the same as subclassing a regular ASDisplayNode. Most importantly, you'll write an -init method, a -layoutSpecThatFits: method for measurement and layout, and, if necessary, a -didLoad method for adding extra gesture recognizers and a -layout method for any extra layout needs. +### 3 Ways to Party -If you don't feel like subclassing you're also free to use the `-initWithView:` or `-initWithViewController:` methods to return nodes with backing views created from an existing view or view controller you already have. +There are three ways in which you can implement the cells you'll use in your ASDK app: subclassing ASCellNode, initializing with an existing ASViewController or using an existing UIView or CALayer. + +#### Subclassing + +Subclassing an ASCellNode is pretty much the same as subclassing a regular ASDisplayNode. + +Most likely, you'll write a few of the following: + + +#### Initializing with an ASViewController + +Say you already have some type of view controller written to display a view in your app. If you want to take that view controller and drop its view in as a cell in one of the scrolling nodes or a pager node its no problem. + +For example, say you already have a view controller written that manages an ASTableNode. To use that table as a page in an ASPagerNode you can use `-initWithViewControllerBlock`. + +
+SwiftObjective-C +
+
+- (ASCellNode *)pagerNode:(ASPagerNode *)pagerNode nodeAtIndex:(NSInteger)index
+{
+    NSArray *animals = self.allAnimals[index];
+    
+    ASCellNode *node = [[ASCellNode alloc] initWithViewControllerBlock:^UIViewController * _Nonnull{
+        return [[AnimalTableNodeController alloc] initWithAnimals:animals];
+    } didLoadBlock:nil];
+    
+    node.preferredFrameSize = pagerNode.bounds.size;
+    
+    return node;
+}
+
+ +
+
+ +And this works for any combo of scrolling container node and UIViewController subclass. You want to embed random view controllers in your collection node? Go for it. + +
+ Notice that you need to set the preferredFrameSize of a node created this way. Normally your nodes will implement -layoutSpecThatFits: but since these don't you'll need give the cell a size. +
+ + +#### Initializing with a UIView or CALayer + +Alternatively, if you already have a UIView or CALayer subclass that you'd like to drop in as cell you can do that instead. + +
+SwiftObjective-C +
+
+- (ASCellNode *)pagerNode:(ASPagerNode *)pagerNode nodeAtIndex:(NSInteger)index
+{
+    NSArray *animal = self.animals[index];
+    
+    ASCellNode *node = [[ASCellNode alloc] initWithViewBlock:^UIView * _Nonnull{
+        return [[SomeAnimalView alloc] initWithAnimal:animal];
+    }];
+
+    node.preferredFrameSize = pagerNode.bounds.size;
+    
+    return node;
+}
+
+ +
+
+ +As you can see, its roughly the same idea. That being said, if you're doing this, you may consider converting the existing UIView subclass to be an ASCellNode subclass in order to gain the advantage of asynchronous display. + +### Never Show Placeholders + +Usually, if a cell hasn't finished its display pass before it has reached the screen it will show placeholders until it has completed drawing its content. + +If placeholders are unacceptable, you can set an ASCellNode's `neverShowPlaceholders` property to `YES`. + +
+SwiftObjective-C +
+
+node.neverShowPlaceholders = YES;
+
+ +
+
+ +With this property set to `YES`, the main thread will be blocked until display has completed for the cell. This is more similar to UIKit, and in fact makes AsyncDisplayKit scrolling visually indistinguishable from UIKit's, except being faster. + +
+Using this option does not eliminate all of the performance advantages of AsyncDisplayKit. Normally, a cell has been preloading and is almost done when it reaches the screen, so the blocking time is very short. Even if the rangeTuningParameters are set to 0 this option outperforms UIKit. While the main thread is waiting, subnode display executes concurrently. +
diff --git a/_docs/containers-astablenode.md b/_docs/containers-astablenode.md index 35e65bee..43d8ba50 100755 --- a/_docs/containers-astablenode.md +++ b/_docs/containers-astablenode.md @@ -183,7 +183,7 @@ For example, you may want to set a table's separator style property. This can be _tableNode.view.allowsSelection = NO; _tableNode.view.separatorStyle = UITableViewCellSeparatorStyleNone; - _tableNode.view.leadingScreensForBatching = 3.0; // overriding default of 2.0 + _tableNode.view.leadingScreensForBatching = 3.0; // default is 2.0 } @@ -193,7 +193,7 @@ override func viewDidLoad() { tableNode.view.allowsSelection = false tableNode.view.separatorStyle = .None - tableNode.view.leadingScreensForBatching = 3.0 // overriding default of 2.0 + tableNode.view.leadingScreensForBatching = 3.0 // default is 2.0 } @@ -219,7 +219,6 @@ This is different from UIKit where normally you would have to call reload row / ### Sample Apps with ASTableNodes diff --git a/_docs/control-node.md b/_docs/control-node.md index 7e8c3d42..eba1cdaa 100755 --- a/_docs/control-node.md +++ b/_docs/control-node.md @@ -5,7 +5,86 @@ permalink: /docs/control-node.html next: button-node.html --- -
😑 This page is coming soon...
+ASControlNode is the ASDK equivalent to UIControl. You don't create instantce of ASControlNode directly. Instead, you can use it as a subclassing point when creating controls of your own. In fact, ASTextNode and ASImageNode are subclasses of ASControlNode which means they can easily be used in the same way you would normally use a UIButton. -####Tappable Area Visualization#### -With just one line of code, you can easily visualize the tappable areas of all ASControlNodes in your app using the hit test slop debug tool. +### Control State + +Like UIControl, ASControlNode has a state which defines its appearance and ability to support user interactions. Its state can be one of any state defined by `ASControlState`. + + +
+Objective-C +
+
+typedef NS_OPTIONS(NSUInteger, ASControlState) {
+    ASControlStateNormal       = 0,
+    ASControlStateHighlighted  = 1 << 0,  // used when isHighlighted is set
+    ASControlStateDisabled     = 1 << 1,
+    ASControlStateSelected     = 1 << 2,  // used when isSelected is set
+    ...
+};
+  
+
+
+ +### Target-Action Mechanism + +Also similarly to UIControl, ASControlNode's have a set of events defined which you can react to by assigning a target-action pair. + +The available actions are: +
+Objective-C +
+
+typedef NS_OPTIONS(NSUInteger, ASControlNodeEvent)
+{
+  /** A touch-down event in the control node. */
+  ASControlNodeEventTouchDown         = 1 << 0,
+  /** A repeated touch-down event in the control node; for this event the value of the UITouch tapCount method is greater than one. */
+  ASControlNodeEventTouchDownRepeat   = 1 << 1,
+  /** An event where a finger is dragged inside the bounds of the control node. */
+  ASControlNodeEventTouchDragInside   = 1 << 2,
+  /** An event where a finger is dragged just outside the bounds of the control. */
+  ASControlNodeEventTouchDragOutside  = 1 << 3,
+  /** A touch-up event in the control node where the finger is inside the bounds of the node. */
+  ASControlNodeEventTouchUpInside     = 1 << 4,
+  /** A touch-up event in the control node where the finger is outside the bounds of the node. */
+  ASControlNodeEventTouchUpOutside    = 1 << 5,
+  /** A system event canceling the current touches for the control node. */
+  ASControlNodeEventTouchCancel       = 1 << 6,
+  /** All events, including system events. */
+  ASControlNodeEventAllEvents         = 0xFFFFFFFF
+};
+  
+
+
+ +Assigning a target and action for these events is done with the same methods as a UIControl, namely using `–addTarget:action:forControlEvents:` or `–actionsForTarget:forControlEvent:`. + +### Hit Test Slop + +While all node's have a `hitTestSlop` property, this is usually most useful when dealing with controls. Instead of needing to make your control bigger, or needing to override -hitTest:withEvent: you can just assign a UIEdgeInsets to your control and its boundaries will be expanded accordingly. + +
+SwiftObjective-C +
+
+CGFloat horizontalDiff = (bounds.size.width - _playButton.bounds.size.width)/2;
+CGFloat verticalDiff = (bounds.size.height - _playButton.bounds.size.height)/2;
+
+_playButton.hitTestSlop = UIEdgeInsetsMake(-verticalDiff, -horizontalDiff, -verticalDiff, -horizontalDiff);
+
+ +
+
+ +Remember that, since the property is an inset, you'll need to use negative values in order to expand the size of your tappable region. + +### Hit Test Visualization + +The hit test visualization tool is an option to enable highlighting of the tappable areas of your nodes. To enable it, include `[ASControlNode setEnableHitTestDebug:YES]` in your app delegate in `-application:didFinishLaunchingWithOptions:`. diff --git a/_docs/display-node.md b/_docs/display-node.md index abdd2c2c..2ffdfed8 100755 --- a/_docs/display-node.md +++ b/_docs/display-node.md @@ -41,7 +41,7 @@ Properties of both views and layers are forwarded to nodes and can be easily acc
 ASDisplayNode *node = [[ASDisplayNode alloc] init];
-node.clipsToBounds = YES; 				        // not .masksToBounds
+node.clipsToBounds = YES;				  // not .masksToBounds
 node.borderColor = [UIColor blueColor];  //layer name when there is no UIView equivalent
 
 NSLog(@"Backing layer: %@", node.layer);
@@ -49,7 +49,7 @@ NSLog(@"Backing layer: %@", node.layer);