mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-16 03:09:56 +00:00
Beef up the properties, beef up the demo app
This commit is contained in:
parent
7a6006e627
commit
563d0893a3
@ -94,13 +94,12 @@
|
||||
|
||||
- (void)setNeedsLayout
|
||||
{
|
||||
ASDisplayNodeAssertThreadAffinity(self);
|
||||
CGSize oldSize = self.calculatedSize;
|
||||
[super setNeedsLayout];
|
||||
|
||||
if (_layoutDelegate != nil && self.isNodeLoaded) {
|
||||
BOOL sizeChanged = !CGSizeEqualToSize(oldSize, self.calculatedSize);
|
||||
ASPerformBlockOnMainThread(^{
|
||||
BOOL sizeChanged = !CGSizeEqualToSize(oldSize, self.calculatedSize);
|
||||
[_layoutDelegate nodeDidRelayout:self sizeChanged:sizeChanged];
|
||||
});
|
||||
}
|
||||
|
||||
@ -628,7 +628,6 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c)
|
||||
|
||||
- (ASLayout *)measureWithSizeRange:(ASSizeRange)constrainedSize completion:(void(^)())completion
|
||||
{
|
||||
ASDisplayNodeAssertThreadAffinity(self);
|
||||
ASDN::MutexLocker l(_propertyLock);
|
||||
if (![self __shouldSize])
|
||||
return nil;
|
||||
@ -1868,7 +1867,7 @@ void recursivelyTriggerDisplayForLayer(CALayer *layer, BOOL shouldBlock)
|
||||
|
||||
- (ASLayout *)calculateLayoutThatFits:(ASSizeRange)constrainedSize
|
||||
{
|
||||
ASDisplayNodeAssertThreadAffinity(self);
|
||||
ASDN::MutexLocker l(_propertyLock);
|
||||
if (_methodOverrides & ASDisplayNodeMethodOverrideLayoutSpecThatFits) {
|
||||
ASLayoutSpec *layoutSpec = [self layoutSpecThatFits:constrainedSize];
|
||||
layoutSpec.isMutable = NO;
|
||||
@ -1895,25 +1894,25 @@ void recursivelyTriggerDisplayForLayer(CALayer *layer, BOOL shouldBlock)
|
||||
|
||||
- (CGSize)calculateSizeThatFits:(CGSize)constrainedSize
|
||||
{
|
||||
ASDisplayNodeAssertThreadAffinity(self);
|
||||
ASDN::MutexLocker l(_propertyLock);
|
||||
return _preferredFrameSize;
|
||||
}
|
||||
|
||||
- (ASLayoutSpec *)layoutSpecThatFits:(ASSizeRange)constrainedSize
|
||||
{
|
||||
ASDisplayNodeAssertThreadAffinity(self);
|
||||
ASDN::MutexLocker l(_propertyLock);
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (ASLayout *)calculatedLayout
|
||||
{
|
||||
ASDisplayNodeAssertThreadAffinity(self);
|
||||
ASDN::MutexLocker l(_propertyLock);
|
||||
return _layout;
|
||||
}
|
||||
|
||||
- (CGSize)calculatedSize
|
||||
{
|
||||
ASDisplayNodeAssertThreadAffinity(self);
|
||||
ASDN::MutexLocker l(_propertyLock);
|
||||
return _layout.size;
|
||||
}
|
||||
|
||||
@ -1944,7 +1943,7 @@ void recursivelyTriggerDisplayForLayer(CALayer *layer, BOOL shouldBlock)
|
||||
|
||||
- (void)invalidateCalculatedLayout
|
||||
{
|
||||
ASDisplayNodeAssertThreadAffinity(self);
|
||||
ASDN::MutexLocker l(_propertyLock);
|
||||
// This will cause -measureWithSizeRange: to actually compute the size instead of returning the previously cached size
|
||||
_flags.isMeasured = NO;
|
||||
}
|
||||
|
||||
@ -335,9 +335,9 @@ if (shouldApply) { _layer.layerProperty = (layerValueExpr); } else { _pendingVie
|
||||
{
|
||||
_bridge_prologue_write;
|
||||
_setToLayer(opaque, newOpaque);
|
||||
|
||||
// FIXME: Would like to setNeedsDisplay if opaqueness changed, but
|
||||
// not safe to read old value in background.
|
||||
// NOTE: If we're in the background, then when the pending state
|
||||
// is applied to the view on main, we will call `setNeedsDisplay` if
|
||||
// the new opaque value doesn't match the one on the layer.
|
||||
}
|
||||
|
||||
- (BOOL)isUserInteractionEnabled
|
||||
@ -539,8 +539,9 @@ if (shouldApply) { _layer.layerProperty = (layerValueExpr); } else { _pendingVie
|
||||
{
|
||||
_bridge_prologue_write;
|
||||
_setToLayer(backgroundColor, newBackgroundColor.CGColor);
|
||||
// FIXME: Would like to setNeedsDisplay if background color changed, but
|
||||
// not safe to read old color in background.
|
||||
// NOTE: If we're in the background, then when the pending state
|
||||
// is applied to the view on main, we will call `setNeedsDisplay` if
|
||||
// the new background color doesn't match the one on the layer.
|
||||
}
|
||||
|
||||
- (UIColor *)tintColor
|
||||
|
||||
@ -557,6 +557,13 @@ static UIColor *defaultTintColor = nil;
|
||||
- (void)applyToLayer:(CALayer *)layer
|
||||
{
|
||||
ASPendingStateFlags flags = _flags;
|
||||
|
||||
if (flags.needsDisplay
|
||||
|| (flags.setOpaque && opaque != layer.opaque)
|
||||
|| (flags.setBackgroundColor && !CGColorEqualToColor(backgroundColor, layer.backgroundColor))) {
|
||||
[layer setNeedsDisplay];
|
||||
}
|
||||
|
||||
if (flags.setAnchorPoint)
|
||||
layer.anchorPoint = anchorPoint;
|
||||
|
||||
@ -629,9 +636,6 @@ static UIColor *defaultTintColor = nil;
|
||||
if (flags.setEdgeAntialiasingMask)
|
||||
layer.edgeAntialiasingMask = edgeAntialiasingMask;
|
||||
|
||||
if (flags.needsDisplay)
|
||||
[layer setNeedsDisplay];
|
||||
|
||||
if (flags.needsLayout)
|
||||
[layer setNeedsLayout];
|
||||
|
||||
@ -658,6 +662,12 @@ static UIColor *defaultTintColor = nil;
|
||||
CALayer *layer = view.layer;
|
||||
|
||||
ASPendingStateFlags flags = _flags;
|
||||
if (flags.needsDisplay
|
||||
|| (flags.setOpaque && opaque != view.opaque)
|
||||
|| (flags.setBackgroundColor && !CGColorEqualToColor(backgroundColor, layer.backgroundColor))) {
|
||||
[view setNeedsDisplay];
|
||||
}
|
||||
|
||||
if (flags.setAnchorPoint)
|
||||
layer.anchorPoint = anchorPoint;
|
||||
|
||||
@ -752,9 +762,6 @@ static UIColor *defaultTintColor = nil;
|
||||
if (flags.setEdgeAntialiasingMask)
|
||||
layer.edgeAntialiasingMask = edgeAntialiasingMask;
|
||||
|
||||
if (flags.needsDisplay)
|
||||
[view setNeedsDisplay];
|
||||
|
||||
if (flags.needsLayout)
|
||||
[view setNeedsLayout];
|
||||
|
||||
|
||||
@ -11,6 +11,8 @@
|
||||
CCD3736F1C751C8A00AB7199 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CCD3736E1C751C8A00AB7199 /* ViewController.swift */; };
|
||||
CCD373741C751C8A00AB7199 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = CCD373731C751C8A00AB7199 /* Assets.xcassets */; };
|
||||
CCD373771C751C8A00AB7199 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = CCD373751C751C8A00AB7199 /* LaunchScreen.storyboard */; };
|
||||
CCD3737F1C7520AB00AB7199 /* DemoCellNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = CCD3737E1C7520AB00AB7199 /* DemoCellNode.swift */; };
|
||||
CCD373811C75228900AB7199 /* Utilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = CCD373801C75228900AB7199 /* Utilities.swift */; };
|
||||
FE56E788869496B3522E8AE2 /* Pods.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D966CA4D089E4178A58E447C /* Pods.framework */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
@ -23,6 +25,8 @@
|
||||
CCD373731C751C8A00AB7199 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||
CCD373761C751C8A00AB7199 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
||||
CCD373781C751C8A00AB7199 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
CCD3737E1C7520AB00AB7199 /* DemoCellNode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DemoCellNode.swift; sourceTree = "<group>"; };
|
||||
CCD373801C75228900AB7199 /* Utilities.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Utilities.swift; sourceTree = "<group>"; };
|
||||
D966CA4D089E4178A58E447C /* Pods.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
@ -78,6 +82,8 @@
|
||||
children = (
|
||||
CCD3736C1C751C8A00AB7199 /* AppDelegate.swift */,
|
||||
CCD3736E1C751C8A00AB7199 /* ViewController.swift */,
|
||||
CCD373801C75228900AB7199 /* Utilities.swift */,
|
||||
CCD3737E1C7520AB00AB7199 /* DemoCellNode.swift */,
|
||||
CCD373731C751C8A00AB7199 /* Assets.xcassets */,
|
||||
CCD373751C751C8A00AB7199 /* LaunchScreen.storyboard */,
|
||||
CCD373781C751C8A00AB7199 /* Info.plist */,
|
||||
@ -206,7 +212,9 @@
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
CCD3737F1C7520AB00AB7199 /* DemoCellNode.swift in Sources */,
|
||||
CCD3736F1C751C8A00AB7199 /* ViewController.swift in Sources */,
|
||||
CCD373811C75228900AB7199 /* Utilities.swift in Sources */,
|
||||
CCD3736D1C751C8A00AB7199 /* AppDelegate.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
|
||||
@ -0,0 +1,87 @@
|
||||
//
|
||||
// DemoCellNode.swift
|
||||
// BackgroundPropertySetting
|
||||
//
|
||||
// Created by Adlai Holler on 2/17/16.
|
||||
// Copyright © 2016 Adlai Holler. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import AsyncDisplayKit
|
||||
|
||||
final class DemoCellNode: ASCellNode {
|
||||
let childA = ASDisplayNode()
|
||||
let childB = ASDisplayNode()
|
||||
var state = State.Right
|
||||
|
||||
override init() {
|
||||
super.init()
|
||||
usesImplicitHierarchyManagement = true
|
||||
}
|
||||
|
||||
override func layoutSpecThatFits(constrainedSize: ASSizeRange) -> ASLayoutSpec {
|
||||
let specA = ASRatioLayoutSpec(ratio: 1, child: childA)
|
||||
specA.flexBasis = ASRelativeDimensionMakeWithPoints(1)
|
||||
specA.flexGrow = true
|
||||
let specB = ASRatioLayoutSpec(ratio: 1, child: childB)
|
||||
specB.flexBasis = ASRelativeDimensionMakeWithPoints(1)
|
||||
specB.flexGrow = true
|
||||
let children = state.isReverse ? [ specB, specA ] : [ specA, specB ]
|
||||
let direction: ASStackLayoutDirection = state.isVertical ? .Vertical : .Horizontal
|
||||
return ASStackLayoutSpec(direction: direction,
|
||||
spacing: 20,
|
||||
justifyContent: .SpaceAround,
|
||||
alignItems: .Center,
|
||||
children: children)
|
||||
}
|
||||
|
||||
override func animateLayoutTransition(context: ASContextTransitioning!) {
|
||||
childA.frame = context.initialFrameForNode(childA)
|
||||
childB.frame = context.initialFrameForNode(childB)
|
||||
let tinyDelay = drand48() / 10
|
||||
UIView.animateWithDuration(0.5, delay: tinyDelay, usingSpringWithDamping: 0.9, initialSpringVelocity: 1.5, options: .BeginFromCurrentState, animations: { () -> Void in
|
||||
self.childA.frame = context.finalFrameForNode(self.childA)
|
||||
self.childB.frame = context.finalFrameForNode(self.childB)
|
||||
}, completion: {
|
||||
context.completeTransition($0)
|
||||
})
|
||||
}
|
||||
|
||||
enum State {
|
||||
case Right
|
||||
case Up
|
||||
case Left
|
||||
case Down
|
||||
|
||||
var isVertical: Bool {
|
||||
switch self {
|
||||
case .Up, .Down:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
var isReverse: Bool {
|
||||
switch self {
|
||||
case .Left, .Up:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
mutating func advance() {
|
||||
switch self {
|
||||
case .Right:
|
||||
self = .Up
|
||||
case .Up:
|
||||
self = .Left
|
||||
case .Left:
|
||||
self = .Down
|
||||
case .Down:
|
||||
self = .Right
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,15 @@
|
||||
//
|
||||
// Utilities.swift
|
||||
// BackgroundPropertySetting
|
||||
//
|
||||
// Created by Adlai Holler on 2/17/16.
|
||||
// Copyright © 2016 Adlai Holler. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
extension UIColor {
|
||||
static func random() -> UIColor {
|
||||
return UIColor(red: CGFloat(drand48()), green: CGFloat(drand48()), blue: CGFloat(drand48()), alpha: 1.0)
|
||||
}
|
||||
}
|
||||
@ -9,56 +9,87 @@
|
||||
import UIKit
|
||||
import AsyncDisplayKit
|
||||
|
||||
final class ViewController: ASViewController, ASTableDelegate, ASTableDataSource {
|
||||
final class ViewController: ASViewController, ASCollectionDelegate, ASCollectionDataSource {
|
||||
let itemCount = 1000
|
||||
|
||||
var tableNode: ASTableNode {
|
||||
return node as! ASTableNode
|
||||
let itemSize: CGSize
|
||||
let padding: CGFloat
|
||||
var collectionNode: ASCollectionNode {
|
||||
return node as! ASCollectionNode
|
||||
}
|
||||
|
||||
init() {
|
||||
super.init(node: ASTableNode(style: .Plain))
|
||||
navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Update", style: .Plain, target: self, action: "didTapUpdateButton")
|
||||
tableNode.delegate = self
|
||||
tableNode.dataSource = self
|
||||
title = "Background Node Updating Demo"
|
||||
let layout = UICollectionViewFlowLayout()
|
||||
(padding, itemSize) = ViewController.computeLayoutSizesForMainScreen()
|
||||
layout.minimumInteritemSpacing = padding
|
||||
layout.minimumLineSpacing = padding
|
||||
super.init(node: ASCollectionNode(collectionViewLayout: layout))
|
||||
navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Color", style: .Plain, target: self, action: "didTapColorsButton")
|
||||
navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Layout", style: .Plain, target: self, action: "didTapLayoutButton")
|
||||
collectionNode.delegate = self
|
||||
collectionNode.dataSource = self
|
||||
title = "Background Updating"
|
||||
}
|
||||
|
||||
required init?(coder aDecoder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
let rowCount = 20
|
||||
|
||||
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||||
return rowCount
|
||||
// MARK: ASCollectionDataSource
|
||||
|
||||
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
|
||||
return itemCount
|
||||
}
|
||||
|
||||
func tableView(tableView: ASTableView, nodeBlockForRowAtIndexPath indexPath: NSIndexPath) -> ASCellNodeBlock {
|
||||
func collectionView(collectionView: ASCollectionView, nodeBlockForItemAtIndexPath indexPath: NSIndexPath) -> ASCellNodeBlock {
|
||||
return {
|
||||
let node = ASCellNode()
|
||||
node.backgroundColor = getRandomColor()
|
||||
let node = DemoCellNode()
|
||||
node.backgroundColor = UIColor.random()
|
||||
node.childA.backgroundColor = UIColor.random()
|
||||
node.childB.backgroundColor = UIColor.random()
|
||||
return node
|
||||
}
|
||||
}
|
||||
|
||||
@objc private func didTapUpdateButton() {
|
||||
let currentlyVisibleNodes = tableNode.view.visibleNodes()
|
||||
func collectionView(collectionView: ASCollectionView, constrainedSizeForNodeAtIndexPath indexPath: NSIndexPath) -> ASSizeRange {
|
||||
return ASSizeRangeMake(itemSize, itemSize)
|
||||
}
|
||||
|
||||
// MARK: Action Handling
|
||||
|
||||
@objc private func didTapColorsButton() {
|
||||
let currentlyVisibleNodes = collectionNode.view.visibleNodes()
|
||||
let queue = dispatch_get_global_queue(QOS_CLASS_DEFAULT, 0)
|
||||
dispatch_async(queue) {
|
||||
for case let node as ASCellNode in currentlyVisibleNodes {
|
||||
node.backgroundColor = getRandomColor()
|
||||
for case let node as DemoCellNode in currentlyVisibleNodes {
|
||||
node.backgroundColor = UIColor.random()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func getRandomColor() -> UIColor{
|
||||
|
||||
let randomRed:CGFloat = CGFloat(drand48())
|
||||
|
||||
let randomGreen:CGFloat = CGFloat(drand48())
|
||||
|
||||
let randomBlue:CGFloat = CGFloat(drand48())
|
||||
|
||||
return UIColor(red: randomRed, green: randomGreen, blue: randomBlue, alpha: 1.0)
|
||||
|
||||
|
||||
@objc private func didTapLayoutButton() {
|
||||
let currentlyVisibleNodes = collectionNode.view.visibleNodes()
|
||||
let queue = dispatch_get_global_queue(QOS_CLASS_DEFAULT, 0)
|
||||
dispatch_async(queue) {
|
||||
for case let node as DemoCellNode in currentlyVisibleNodes {
|
||||
node.state.advance()
|
||||
node.setNeedsLayout()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Static
|
||||
|
||||
static func computeLayoutSizesForMainScreen() -> (padding: CGFloat, itemSize: CGSize) {
|
||||
let numberOfColumns = 4
|
||||
let screen = UIScreen.mainScreen()
|
||||
let scale = screen.scale
|
||||
let screenWidth = Int(screen.bounds.width * screen.scale)
|
||||
let itemWidthPx = (screenWidth - (numberOfColumns - 1)) / numberOfColumns
|
||||
let leftover = screenWidth - itemWidthPx * numberOfColumns
|
||||
let paddingPx = leftover / (numberOfColumns - 1)
|
||||
let itemDimension = CGFloat(itemWidthPx) / scale
|
||||
let padding = CGFloat(paddingPx) / scale
|
||||
return (padding: padding, itemSize: CGSize(width: itemDimension, height: itemDimension))
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user