Access on/off labels accessibility setting for switches on iOS (flutter/engine#30764)

This commit is contained in:
Rutger Vromans
2022-03-07 23:51:10 +01:00
committed by GitHub
parent 50e71320e0
commit 8c42b89cdf
6 changed files with 95 additions and 18 deletions

View File

@@ -771,6 +771,7 @@ class AccessibilityFeatures {
static const int _kBoldTextIndex = 1 << 3;
static const int _kReduceMotionIndex = 1 << 4;
static const int _kHighContrastIndex = 1 << 5;
static const int _kOnOffSwitchLabelsIndex = 1 << 6;
// A bitfield which represents each enabled feature.
final int _index;
@@ -803,6 +804,11 @@ class AccessibilityFeatures {
/// Only supported on iOS.
bool get highContrast => _kHighContrastIndex & _index != 0;
/// The platform is requesting to show on/off labels inside switches.
///
/// Only supported on iOS.
bool get onOffSwitchLabels => _kOnOffSwitchLabelsIndex & _index != 0;
@override
String toString() {
final List<String> features = <String>[];
@@ -818,6 +824,8 @@ class AccessibilityFeatures {
features.add('reduceMotion');
if (highContrast)
features.add('highContrast');
if (onOffSwitchLabels)
features.add('onOffSwitchLabels');
return 'AccessibilityFeatures$features';
}

View File

@@ -35,6 +35,7 @@ enum class AccessibilityFeatureFlag : int32_t {
kBoldText = 1 << 3,
kReduceMotion = 1 << 4,
kHighContrast = 1 << 5,
kOnOffSwitchLabels = 1 << 6,
};
//--------------------------------------------------------------------------

View File

@@ -148,6 +148,7 @@ class AccessibilityFeatures {
static const int _kBoldTextIndex = 1 << 3;
static const int _kReduceMotionIndex = 1 << 4;
static const int _kHighContrastIndex = 1 << 5;
static const int _kOnOffSwitchLabelsIndex = 1 << 6;
// A bitfield which represents each enabled feature.
final int _index;
@@ -158,6 +159,7 @@ class AccessibilityFeatures {
bool get boldText => _kBoldTextIndex & _index != 0;
bool get reduceMotion => _kReduceMotionIndex & _index != 0;
bool get highContrast => _kHighContrastIndex & _index != 0;
bool get onOffSwitchLabels => _kOnOffSwitchLabelsIndex & _index != 0;
@override
String toString() {
@@ -180,6 +182,9 @@ class AccessibilityFeatures {
if (highContrast) {
features.add('highContrast');
}
if (onOffSwitchLabels) {
features.add('onOffSwitchLabels');
}
return 'AccessibilityFeatures$features';
}

View File

@@ -331,6 +331,13 @@ typedef enum UIAccessibilityContrast : NSInteger {
name:UIAccessibilityDarkerSystemColorsStatusDidChangeNotification
object:nil];
if (@available(iOS 13.0, *)) {
[center addObserver:self
selector:@selector(onAccessibilityStatusChanged:)
name:UIAccessibilityOnOffSwitchLabelsDidChangeNotification
object:nil];
}
[center addObserver:self
selector:@selector(onUserSettingsChanged:)
name:UIContentSizeCategoryDidChangeNotification
@@ -1417,19 +1424,7 @@ static flutter::PointerData::DeviceKind DeviceKindFromTouchType(UITouch* touch)
return;
}
auto platformView = [_engine.get() platformView];
int32_t flags = 0;
if (UIAccessibilityIsInvertColorsEnabled()) {
flags |= static_cast<int32_t>(flutter::AccessibilityFeatureFlag::kInvertColors);
}
if (UIAccessibilityIsReduceMotionEnabled()) {
flags |= static_cast<int32_t>(flutter::AccessibilityFeatureFlag::kReduceMotion);
}
if (UIAccessibilityIsBoldTextEnabled()) {
flags |= static_cast<int32_t>(flutter::AccessibilityFeatureFlag::kBoldText);
}
if (UIAccessibilityDarkerSystemColorsEnabled()) {
flags |= static_cast<int32_t>(flutter::AccessibilityFeatureFlag::kHighContrast);
}
int32_t flags = [self accessibilityFlags];
#if TARGET_OS_SIMULATOR
// There doesn't appear to be any way to determine whether the accessibility
// inspector is enabled on the simulator. We conservatively always turn on the
@@ -1447,6 +1442,35 @@ static flutter::PointerData::DeviceKind DeviceKindFromTouchType(UITouch* touch)
#endif
}
- (int32_t)accessibilityFlags {
int32_t flags = 0;
if (UIAccessibilityIsInvertColorsEnabled()) {
flags |= static_cast<int32_t>(flutter::AccessibilityFeatureFlag::kInvertColors);
}
if (UIAccessibilityIsReduceMotionEnabled()) {
flags |= static_cast<int32_t>(flutter::AccessibilityFeatureFlag::kReduceMotion);
}
if (UIAccessibilityIsBoldTextEnabled()) {
flags |= static_cast<int32_t>(flutter::AccessibilityFeatureFlag::kBoldText);
}
if (UIAccessibilityDarkerSystemColorsEnabled()) {
flags |= static_cast<int32_t>(flutter::AccessibilityFeatureFlag::kHighContrast);
}
if ([FlutterViewController accessibilityIsOnOffSwitchLabelsEnabled]) {
flags |= static_cast<int32_t>(flutter::AccessibilityFeatureFlag::kOnOffSwitchLabels);
}
return flags;
}
+ (BOOL)accessibilityIsOnOffSwitchLabelsEnabled {
if (@available(iOS 13, *)) {
return UIAccessibilityIsOnOffSwitchLabelsEnabled();
} else {
return NO;
}
}
#pragma mark - Set user settings
- (void)traitCollectionDidChange:(UITraitCollection*)previousTraitCollection {

View File

@@ -6,6 +6,7 @@
#import <XCTest/XCTest.h>
#include "flutter/fml/platform/darwin/message_loop_darwin.h"
#import "flutter/lib/ui/window/platform_configuration.h"
#import "flutter/lib/ui/window/viewport_metrics.h"
#import "flutter/shell/platform/darwin/common/framework/Headers/FlutterBinaryMessenger.h"
#import "flutter/shell/platform/darwin/common/framework/Headers/FlutterMacros.h"
@@ -25,10 +26,6 @@ FLUTTER_ASSERT_ARC
userData:(nullable void*)userData;
@end
namespace flutter {
class PointerDataPacket {};
}
/// Sometimes we have to use a custom mock to avoid retain cycles in OCMock.
/// Used for testing low memory notification.
@interface FlutterEnginePartialMock : FlutterEngine
@@ -617,6 +614,46 @@ typedef enum UIAccessibilityContrast : NSInteger {
[mockTraitCollection stopMocking];
}
- (void)testItReportsAccessibilityOnOffSwitchLabelsFlagNotSet {
if (@available(iOS 13, *)) {
// noop
} else {
return;
}
// Setup test.
FlutterViewController* viewController =
[[FlutterViewController alloc] initWithEngine:self.mockEngine nibName:nil bundle:nil];
id partialMockViewController = OCMPartialMock(viewController);
OCMStub([partialMockViewController accessibilityIsOnOffSwitchLabelsEnabled]).andReturn(NO);
// Exercise behavior under test.
int32_t flags = [partialMockViewController accessibilityFlags];
// Verify behavior.
XCTAssert((flags & (int32_t)flutter::AccessibilityFeatureFlag::kOnOffSwitchLabels) == 0);
}
- (void)testItReportsAccessibilityOnOffSwitchLabelsFlagSet {
if (@available(iOS 13, *)) {
// noop
} else {
return;
}
// Setup test.
FlutterViewController* viewController =
[[FlutterViewController alloc] initWithEngine:self.mockEngine nibName:nil bundle:nil];
id partialMockViewController = OCMPartialMock(viewController);
OCMStub([partialMockViewController accessibilityIsOnOffSwitchLabelsEnabled]).andReturn(YES);
// Exercise behavior under test.
int32_t flags = [partialMockViewController accessibilityFlags];
// Verify behavior.
XCTAssert((flags & (int32_t)flutter::AccessibilityFeatureFlag::kOnOffSwitchLabels) != 0);
}
- (void)testPerformOrientationUpdateForcesOrientationChange {
[self orientationTestWithOrientationUpdate:UIInterfaceOrientationMaskPortrait
currentOrientation:UIInterfaceOrientationLandscapeLeft
@@ -1052,7 +1089,7 @@ typedef enum UIAccessibilityContrast : NSInteger {
[vc scrollEvent:mockPanGestureRecognizer];
[[[self.mockEngine verify] ignoringNonObjectArgs]
dispatchPointerDataPacket:std::make_unique<flutter::PointerDataPacket>()];
dispatchPointerDataPacket:std::make_unique<flutter::PointerDataPacket>(0)];
}
@end

View File

@@ -29,6 +29,7 @@ extern NSNotificationName const FlutterViewControllerShowHomeIndicator;
@interface FlutterViewController () <FlutterViewResponder>
@property(class, nonatomic, readonly) BOOL accessibilityIsOnOffSwitchLabelsEnabled;
@property(nonatomic, readonly) BOOL isPresentingViewController;
@property(nonatomic, readonly) BOOL isVoiceOverRunning;
@property(nonatomic, retain) FlutterKeyboardManager* keyboardManager;
@@ -45,6 +46,7 @@ extern NSNotificationName const FlutterViewControllerShowHomeIndicator;
nextAction:(void (^)())nextAction API_AVAILABLE(ios(13.4));
- (void)addInternalPlugins;
- (void)deregisterNotifications;
- (int32_t)accessibilityFlags;
@end
#endif // FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_SOURCE_FLUTTERVIEWCONTROLLER_INTERNAL_H_