mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-16 19:30:29 +00:00
Add accessibility support for shouldRasterizeDescendants and layerBacked nodese
This commit is contained in:
parent
9c29d0efa8
commit
03a7c55d59
@ -18,6 +18,8 @@
|
|||||||
#import "ASDisplayNode+FrameworkPrivate.h"
|
#import "ASDisplayNode+FrameworkPrivate.h"
|
||||||
#import "ASDisplayNode+Subclasses.h"
|
#import "ASDisplayNode+Subclasses.h"
|
||||||
|
|
||||||
|
#import <queue>
|
||||||
|
|
||||||
@interface _ASDisplayView ()
|
@interface _ASDisplayView ()
|
||||||
@property (nonatomic, assign, readwrite) ASDisplayNode *asyncdisplaykit_node;
|
@property (nonatomic, assign, readwrite) ASDisplayNode *asyncdisplaykit_node;
|
||||||
|
|
||||||
@ -380,6 +382,22 @@
|
|||||||
|
|
||||||
#pragma mark - Accessibility
|
#pragma mark - Accessibility
|
||||||
|
|
||||||
|
static BOOL ASNodeValidForAccessibility(ASDisplayNode *node)
|
||||||
|
{
|
||||||
|
if (node.isAccessibilityElement) {
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node.isLayerBacked) {
|
||||||
|
// Assume for now that all nodes that have an accessibility label or
|
||||||
|
return node.accessibilityLabel.length > 0 ||
|
||||||
|
node.accessibilityValue.length > 0 ||
|
||||||
|
((node.accessibilityTraits & UIAccessibilityTraitNone) != UIAccessibilityTraitNone);
|
||||||
|
}
|
||||||
|
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
static const char *ASDisplayNodeAssociatedNodeKey = "ASAssociatedNode";
|
static const char *ASDisplayNodeAssociatedNodeKey = "ASAssociatedNode";
|
||||||
|
|
||||||
@implementation UIAccessibilityElement (_ASDisplayView)
|
@implementation UIAccessibilityElement (_ASDisplayView)
|
||||||
@ -408,16 +426,50 @@ static const char *ASDisplayNodeAssociatedNodeKey = "ASAssociatedNode";
|
|||||||
|
|
||||||
- (NSArray *)accessibleElements
|
- (NSArray *)accessibleElements
|
||||||
{
|
{
|
||||||
ASDisplayNode *asyncDisplayKitNode = self.asyncdisplaykit_node;
|
|
||||||
if ( _accessibleElements != nil ) {
|
if ( _accessibleElements != nil ) {
|
||||||
return _accessibleElements;
|
return _accessibleElements;
|
||||||
}
|
}
|
||||||
|
|
||||||
_accessibleElements = [[NSMutableArray alloc] init];
|
_accessibleElements = [[NSMutableArray alloc] init];
|
||||||
|
|
||||||
|
ASDisplayNode *selfNode = self.asyncdisplaykit_node;
|
||||||
|
|
||||||
// Create UI accessiblity elements for each subnode that represent the subnode within the accessibility container
|
// Handle rasterize case
|
||||||
for (ASDisplayNode *subnode in asyncDisplayKitNode.subnodes) {
|
if (selfNode.shouldRasterizeDescendants) {
|
||||||
if (subnode.isAccessibilityElement || [subnode accessibilityElementCount] > 0) {
|
// In this case we have to go through the whole subnodes tree in BFS fashion and create all
|
||||||
|
// accessibility elements ourselves as the view hierarchy is flattened
|
||||||
|
|
||||||
|
// Queue used to keep track of subnodes while traversing this layout in a BFS fashion.
|
||||||
|
std::queue<ASDisplayNode *> queue;
|
||||||
|
queue.push(selfNode);
|
||||||
|
|
||||||
|
while (!queue.empty()) {
|
||||||
|
ASDisplayNode *node = queue.front();
|
||||||
|
queue.pop();
|
||||||
|
|
||||||
|
// Check if we have to add the node to the accessiblity nodes as it's an accessiblity element
|
||||||
|
if (node != selfNode && ASNodeValidForAccessibility(node)) {
|
||||||
|
UIAccessibilityElement *accessibilityElement = [[UIAccessibilityElement alloc] initWithAccessibilityContainer:self];
|
||||||
|
accessibilityElement.asyncdisplaykit_node = node;
|
||||||
|
[_accessibleElements addObject:accessibilityElement];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add all subnodes to process in next step
|
||||||
|
for (int i = 0; i < node.subnodes.count; i++)
|
||||||
|
queue.push(node.subnodes[i]);
|
||||||
|
}
|
||||||
|
return _accessibleElements;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle not rasterize case
|
||||||
|
// Create UI accessiblity elements for each subnode that represent an elment within the accessibility container
|
||||||
|
for (ASDisplayNode *subnode in selfNode.subnodes) {
|
||||||
|
// Check if this subnode is a UIAccessibilityContainer
|
||||||
|
if (!subnode.isAccessibilityElement && [subnode accessibilityElementCount] > 0) {
|
||||||
|
// We are good and the view is an UIAccessibilityContainer so add that
|
||||||
|
[_accessibleElements addObject:subnode.view];
|
||||||
|
} else if (ASNodeValidForAccessibility(subnode)) {
|
||||||
|
// Create a accessiblity element from the subnode
|
||||||
UIAccessibilityElement *accessibilityElement = [[UIAccessibilityElement alloc] initWithAccessibilityContainer:self];
|
UIAccessibilityElement *accessibilityElement = [[UIAccessibilityElement alloc] initWithAccessibilityContainer:self];
|
||||||
accessibilityElement.asyncdisplaykit_node = subnode;
|
accessibilityElement.asyncdisplaykit_node = subnode;
|
||||||
[_accessibleElements addObject:accessibilityElement];
|
[_accessibleElements addObject:accessibilityElement];
|
||||||
@ -434,18 +486,28 @@ static const char *ASDisplayNodeAssociatedNodeKey = "ASAssociatedNode";
|
|||||||
|
|
||||||
- (id)accessibilityElementAtIndex:(NSInteger)index
|
- (id)accessibilityElementAtIndex:(NSInteger)index
|
||||||
{
|
{
|
||||||
UIAccessibilityElement *element = [self accessibleElements][index];
|
UIAccessibilityElement *accessibilityElement = [[self accessibleElements] objectAtIndex:index];
|
||||||
ASDisplayNode *subnode = element.asyncdisplaykit_node;
|
ASDisplayNode *accessibilityElementNode = accessibilityElement.asyncdisplaykit_node;
|
||||||
if (subnode == nil) {
|
if (accessibilityElementNode == nil) {
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We have to update the accessiblity frame in accessibilityElementAtIndex: as the accessibility frame is in screen
|
// We have to update the accessiblity frame in accessibilityElementAtIndex: as the accessibility frame is in screen
|
||||||
// coordinates and between creating the accessibilityElement and returning it in accessibilityElementAtIndex:
|
// coordinates and between creating the accessibilityElement and returning it in accessibilityElementAtIndex:
|
||||||
// the frame can change
|
// the frame can change
|
||||||
element.accessibilityFrame = UIAccessibilityConvertFrameToScreenCoordinates(subnode.frame, self);
|
|
||||||
|
|
||||||
return element;
|
// Handle if node is rasterized
|
||||||
|
ASDisplayNode *selfNode = self.asyncdisplaykit_node;
|
||||||
|
if (selfNode.shouldRasterizeDescendants) {
|
||||||
|
// We need to convert the accessibilityElementNode frame into the coordinate system of the selfNode
|
||||||
|
CGRect frame = [selfNode convertRect:accessibilityElementNode.bounds fromNode:accessibilityElementNode];
|
||||||
|
accessibilityElement.accessibilityFrame = UIAccessibilityConvertFrameToScreenCoordinates(frame, self);
|
||||||
|
return accessibilityElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle non rasterized case
|
||||||
|
accessibilityElement.accessibilityFrame = UIAccessibilityConvertFrameToScreenCoordinates(accessibilityElementNode.frame, self);
|
||||||
|
return accessibilityElement;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSInteger)indexOfAccessibilityElement:(id)element
|
- (NSInteger)indexOfAccessibilityElement:(id)element
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user