mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-24 07:05:35 +00:00
Initial attempt at implementing Display Traits
Initial attempt to get display traits working with ASEnvironment. To get proper ASDisplayTraits support, you must use an ASViewController. The ASViewController implements UITraitCollection-related methods (`traitCollectionDidChange:`, `willTransitionToTraitCollection:withTransitionCoordinator:`, viewWillTransitionToSize:withTransitionCoordinator`) to update the internal ASDisplayTraits and propagate them to subnodes. ASTableNode and ASCollectionNode don't actually have their cells as subnodes, so a little bit of trickery is involved (on `setEnvironment:` the table/collection node gets its data controllers completedNodes and propagates the new traits. see `ASDisplayTraitsCollectionTableSetEnvironmentState`). The data controller also passes the current display traits when creating new cells. ASViewController also supports the ability to return a custom set of display traits. So if you have a modal dialog that should always be told it is in a compact size class, you can set the override block before displaying the VC. A new example, called Display Traits, has been added. It shows how display traits can be used in a ASViewController with a normal ASDisplayNode as its root, as well as in ASViewControllers hosting table nodes and collection nodes. There is also an example of overriding the default display traits of a VC. Please provide feedback!
This commit is contained in:
@@ -14,6 +14,8 @@
|
||||
#import "ASStackLayoutDefines.h"
|
||||
#import "ASRelativeSize.h"
|
||||
|
||||
@protocol ASEnvironment;
|
||||
@class UITraitCollection;
|
||||
|
||||
ASDISPLAYNODE_EXTERN_C_BEGIN
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
@@ -59,17 +61,50 @@ typedef struct ASEnvironmentHierarchyState {
|
||||
unsigned layoutPending:1; // = NO
|
||||
} ASEnvironmentHierarchyState;
|
||||
|
||||
#pragma mark - ASDisplayTraits
|
||||
|
||||
typedef struct ASDisplayTraits {
|
||||
CGFloat displayScale;
|
||||
UIUserInterfaceSizeClass horizontalSizeClass;
|
||||
UIUserInterfaceIdiom userInterfaceIdiom;
|
||||
UIUserInterfaceSizeClass verticalSizeClass;
|
||||
UIForceTouchCapability forceTouchCapability;
|
||||
|
||||
// WARNING:
|
||||
// This pointer is in a C struct and therefore not managed by ARC. It is
|
||||
// an unsafe unretained pointer, so when you dereference it you better be
|
||||
// sure that it is valid.
|
||||
//
|
||||
// Use displayContext when you wish to pass view context specific data along with the
|
||||
// trait collcetion to subnodes. This should be a piece of data owned by an
|
||||
// ASViewController, which will ensure that the data is still valid when laying out
|
||||
// its subviews. When the VC is dealloc'ed, the displayContext it created will also
|
||||
// be dealloced but any subnodes that are hanging around (why would they be?) will now
|
||||
// have a displayContext that points to a bad pointer.
|
||||
//
|
||||
// An added precaution is to call ASDisplayTraitsClearDisplayContext from your ASVC's desctructor
|
||||
// which will propagate a nil displayContext to its subnodes.
|
||||
//__unsafe_unretained id displayContext;
|
||||
id __unsafe_unretained displayContext;
|
||||
} ASDisplayTraits;
|
||||
|
||||
extern void ASDisplayTraitsClearDisplayContext(id<ASEnvironment> rootEnvironment);
|
||||
|
||||
extern ASDisplayTraits ASDisplayTraitsFromUITraitCollection(UITraitCollection *traitCollection);
|
||||
extern BOOL ASDisplayTraitsIsEqualToASDisplayTraits(ASDisplayTraits displayTraits0, ASDisplayTraits displayTraits1);
|
||||
|
||||
#pragma mark - ASEnvironmentState
|
||||
|
||||
typedef struct ASEnvironmentState {
|
||||
struct ASEnvironmentHierarchyState hierarchyState;
|
||||
struct ASEnvironmentLayoutOptionsState layoutOptionsState;
|
||||
struct ASDisplayTraits displayTraits;
|
||||
} ASEnvironmentState;
|
||||
extern ASEnvironmentState ASEnvironmentStateMakeDefault();
|
||||
|
||||
ASDISPLAYNODE_EXTERN_C_END
|
||||
|
||||
@class ASTraitCollection;
|
||||
|
||||
#pragma mark - ASEnvironment
|
||||
|
||||
@@ -93,6 +128,33 @@ ASDISPLAYNODE_EXTERN_C_END
|
||||
/// Classes should implement this method and return YES / NO dependent if upward propagation is enabled or not
|
||||
- (BOOL)supportsUpwardPropagation;
|
||||
|
||||
/// Classes should implement this method and return YES / NO dependent if downware propagation is enabled or not
|
||||
- (BOOL)supportsDownwardPropagation;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
// ASCollection/TableNodes don't actually have ASCellNodes as subnodes. Because of this we can't rely on display trait
|
||||
// downward propagation via ASEnvironment. Instead if the new environmentState has displayTraits that are different from
|
||||
// the cells', then we propagate downward explicitly and request a relayout.
|
||||
//
|
||||
// If there is any new downward propagating state, it should be added to this define.
|
||||
//
|
||||
// This logic is used in both ASCollectionNode and ASTableNode
|
||||
#define ASDisplayTraitsCollectionTableSetEnvironmentState \
|
||||
- (void)setEnvironmentState:(ASEnvironmentState)environmentState\
|
||||
{\
|
||||
ASDisplayTraits oldDisplayTraits = self.environmentState.displayTraits;\
|
||||
[super setEnvironmentState:environmentState];\
|
||||
ASDisplayTraits currentDisplayTraits = environmentState.displayTraits;\
|
||||
if (ASDisplayTraitsIsEqualToASDisplayTraits(currentDisplayTraits, oldDisplayTraits) == NO) {\
|
||||
NSArray<NSArray <ASCellNode *> *> *completedNodes = [self.view.dataController completedNodes];\
|
||||
for (NSArray *sectionArray in completedNodes) {\
|
||||
for (ASCellNode *cellNode in sectionArray) {\
|
||||
ASEnvironmentStatePropagateDown(cellNode, currentDisplayTraits);\
|
||||
[cellNode setNeedsLayout];\
|
||||
}\
|
||||
}\
|
||||
}\
|
||||
}\
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
Reference in New Issue
Block a user