Merge pull request #330 from adkenyon/a11y-fallback-for-reduce-transparency

Fallback background color for A11y reduce transparency
This commit is contained in:
Mikael Sand 2020-04-09 01:20:09 +03:00 committed by GitHub
commit fa4711bf4d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 123 additions and 20 deletions

View File

@ -95,6 +95,8 @@ import { BlurView, VibrancyView } from "@react-native-community/blur";
- `ultraThinMaterialLight` - An adaptable blur effect that creates the appearance of an ultra-thin material. - `ultraThinMaterialLight` - An adaptable blur effect that creates the appearance of an ultra-thin material.
- `blurAmount` (Default: 10, Number) - `blurAmount` (Default: 10, Number)
- `0-100` - Adjusts blur intensity - `0-100` - Adjusts blur intensity
- `reducedTransparencyFallbackColor` (Color) (iOS only)
- `black, white, #rrggbb, etc` - background color to use if accessibility setting ReduceTransparency is enabled
> Note: The maximum `blurAmount` on Android is 32, so higher values will be clamped to 32. > Note: The maximum `blurAmount` on Android is 32, so higher values will be clamped to 32.
@ -122,6 +124,7 @@ export default class Menu extends Component {
viewRef={this.state.viewRef} viewRef={this.state.viewRef}
blurType="light" blurType="light"
blurAmount={10} blurAmount={10}
reducedTransparencyFallbackColor="white"
/> />
<Text>I'm the non blurred text because I got rendered on top of the BlurView</Text> <Text>I'm the non blurred text because I got rendered on top of the BlurView</Text>
</View> </View>
@ -146,9 +149,11 @@ const styles = StyleSheet.create({
In this example, the `Image` component will be blurred, because the `BlurView` in positioned on top. But the `Text` will stay unblurred. In this example, the `Image` component will be blurred, because the `BlurView` in positioned on top. But the `Text` will stay unblurred.
If the [accessibility setting `Reduce Transparency`](https://support.apple.com/guide/iphone/display-settings-iph3e2e1fb0/ios) is enabled the `BlurView` will use `reducedTransparencyFallbackColor` as it's background color rather than blurring. If no `reducedTransparencyFallbackColor` is provided, the`BlurView`will use the default fallback color (white, black, or grey depending on `blurType`)
### VibrancyView ### VibrancyView
**Uses the same properties as `BlurView` (`blurType` and `blurAmount`).** **Uses the same properties as `BlurView` (`blurType`, `blurAmount`, and `reducedTransparencyFallbackColor`).**
> The vibrancy effect lets the content underneath a blurred view show through more vibrantly > The vibrancy effect lets the content underneath a blurred view show through more vibrantly

View File

@ -60,6 +60,7 @@ export default class Basic extends Component {
<BlurView <BlurView
blurType={this.state.blurBlurType} blurType={this.state.blurBlurType}
blurAmount={100} blurAmount={100}
reducedTransparencyFallbackColor={'pink'}
style={[styles.blurView]}> style={[styles.blurView]}>
<Text style={[styles.text, { color: tintColor }]}> <Text style={[styles.text, { color: tintColor }]}>
Blur component ({platform}) Blur component ({platform})
@ -84,6 +85,7 @@ export default class Basic extends Component {
<VibrancyView <VibrancyView
blurType={this.state.vibrancyBlurType} blurType={this.state.vibrancyBlurType}
blurAmount={10} blurAmount={10}
reducedTransparencyFallbackColor={'pink'}
style={[styles.container, styles.blurContainer]}> style={[styles.container, styles.blurContainer]}>
<Text style={styles.text}> <Text style={styles.text}>

3
index.d.ts vendored
View File

@ -2,7 +2,7 @@ import * as React from "react";
import { StyleProp, ViewStyle } from "react-native"; import { StyleProp, ViewStyle } from "react-native";
export interface BlurViewProperties { export interface BlurViewProperties {
blurType: blurType?:
| "xlight" | "xlight"
| "light" | "light"
| "dark" | "dark"
@ -28,6 +28,7 @@ export interface BlurViewProperties {
// tvOS only // tvOS only
| "extraDark" | "extraDark"
blurAmount?: number // 0 - 100 blurAmount?: number // 0 - 100
reducedTransparencyFallbackColor?: string
style?: StyleProp<ViewStyle> style?: StyleProp<ViewStyle>
blurRadius?: number blurRadius?: number
downsampleFactor?: number downsampleFactor?: number

View File

@ -33,8 +33,9 @@ export type BlurType =
| 'extraDark'; | 'extraDark';
export type BlurViewProps = { export type BlurViewProps = {
blurType: BlurType, blurType?: BlurType,
blurAmount: number, // 0 - 100 blurAmount?: number, // 0 - 100,
reducedTransparencyFallbackColor?: String,
style?: ?ViewStyleProp, style?: ?ViewStyleProp,
}; };

View File

@ -3,11 +3,15 @@
@interface BlurView : UIView @interface BlurView : UIView
@property (nonatomic, copy) NSString *blurType; @property (nonatomic, copy, nullable) NSString *blurType;
@property (nonatomic, copy) NSNumber *blurAmount; @property (nonatomic, copy, nullable) NSNumber *blurAmount;
@property (nonatomic, copy, nullable) UIColor *reducedTransparencyFallbackColor;
@property (nonatomic, strong) BlurEffectWithAmount *blurEffect; @property (nonatomic, strong, nullable) BlurEffectWithAmount *blurEffect;
@property (nonatomic, strong) UIVisualEffectView *blurEffectView; @property (nonatomic, strong, nullable) UIVisualEffectView *blurEffectView;
@property (nonatomic, strong, nullable) UIView *reducedTransparencyFallbackView;
- (void)updateBlurEffect; - (void)updateBlurEffect;
- (void)updateFallbackView;
- (BOOL)useReduceTransparencyFallback;
@end @end

View File

@ -7,28 +7,52 @@
@implementation BlurView @implementation BlurView
- (instancetype)initWithFrame:(CGRect)frame { - (instancetype)init
if (self = [super initWithFrame:frame]) { {
self.blurEffectView = [[UIVisualEffectView alloc] init]; if (self = [super init]) {
self.blurEffectView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; [[NSNotificationCenter defaultCenter] addObserver:self
self.blurEffectView.frame = frame; selector:@selector(reduceTransparencyStatusDidChange:)
name:UIAccessibilityReduceTransparencyStatusDidChangeNotification
object:nil];
}
self.blurAmount = @10; return self;
self.blurType = @"dark"; }
[self updateBlurEffect];
self.clipsToBounds = true; - (instancetype)initWithFrame:(CGRect)frame
{
if (self = [super initWithFrame:frame]) {
self.blurEffectView = [[UIVisualEffectView alloc] init];
self.blurEffectView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
self.blurEffectView.frame = frame;
[self addSubview:self.blurEffectView]; self.reducedTransparencyFallbackView = [[UIView alloc] init];
} self.reducedTransparencyFallbackView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
self.reducedTransparencyFallbackView.frame = frame;
return self; self.blurAmount = @10;
self.blurType = @"dark";
[self updateBlurEffect];
[self updateFallbackView];
self.clipsToBounds = true;
[self addSubview:self.blurEffectView];
}
return self;
}
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
} }
- (void)layoutSubviews - (void)layoutSubviews
{ {
[super layoutSubviews]; [super layoutSubviews];
self.blurEffectView.frame = self.bounds; self.blurEffectView.frame = self.bounds;
self.reducedTransparencyFallbackView.frame = self.bounds;
} }
- (void)setBlurType:(NSString *)blurType - (void)setBlurType:(NSString *)blurType
@ -47,6 +71,13 @@
} }
} }
- (void)setReducedTransparencyFallbackColor:(nullable UIColor *)reducedTransparencyFallbackColor
{
if (reducedTransparencyFallbackColor && ![self.reducedTransparencyFallbackColor isEqual:reducedTransparencyFallbackColor]) {
_reducedTransparencyFallbackColor = reducedTransparencyFallbackColor;
[self updateFallbackView];
}
}
- (UIBlurEffectStyle)blurEffectStyle - (UIBlurEffectStyle)blurEffectStyle
{ {
@ -89,6 +120,11 @@
return UIBlurEffectStyleDark; return UIBlurEffectStyleDark;
} }
- (BOOL)useReduceTransparencyFallback
{
return UIAccessibilityIsReduceTransparencyEnabled() == YES && self.reducedTransparencyFallbackColor != NULL;
}
- (void)updateBlurEffect - (void)updateBlurEffect
{ {
UIBlurEffectStyle style = [self blurEffectStyle]; UIBlurEffectStyle style = [self blurEffectStyle];
@ -96,4 +132,32 @@
self.blurEffectView.effect = self.blurEffect; self.blurEffectView.effect = self.blurEffect;
} }
- (void)updateFallbackView
{
if ([self useReduceTransparencyFallback]) {
if (![self.subviews containsObject:self.reducedTransparencyFallbackView]) {
[self insertSubview:self.reducedTransparencyFallbackView atIndex:0];
}
if ([self.subviews containsObject:self.blurEffectView]) {
[self.blurEffectView removeFromSuperview];
}
} else {
if ([self.subviews containsObject:self.reducedTransparencyFallbackView]) {
[self.reducedTransparencyFallbackView removeFromSuperview];
}
if (![self.subviews containsObject:self.blurEffectView]) {
[self insertSubview:self.blurEffectView atIndex:0];
}
}
self.reducedTransparencyFallbackView.backgroundColor = self.reducedTransparencyFallbackColor;
}
- (void)reduceTransparencyStatusDidChange:(__unused NSNotification *)notification
{
[self updateFallbackView];
}
@end @end

View File

@ -12,5 +12,6 @@ RCT_EXPORT_MODULE();
RCT_EXPORT_VIEW_PROPERTY(blurType, NSString); RCT_EXPORT_VIEW_PROPERTY(blurType, NSString);
RCT_EXPORT_VIEW_PROPERTY(blurAmount, NSNumber); RCT_EXPORT_VIEW_PROPERTY(blurAmount, NSNumber);
RCT_EXPORT_VIEW_PROPERTY(reducedTransparencyFallbackColor, UIColor);
@end @end

View File

@ -30,7 +30,11 @@
} }
- (void)insertReactSubview:(id<RCTComponent>)subview atIndex:(NSInteger)atIndex { - (void)insertReactSubview:(id<RCTComponent>)subview atIndex:(NSInteger)atIndex {
if ([self useReduceTransparencyFallback]) {
[self addSubview:(UIView*)subview];
} else {
[self.vibrancyEffectView.contentView addSubview:(UIView*)subview]; [self.vibrancyEffectView.contentView addSubview:(UIView*)subview];
}
} }
- (void)updateBlurEffect - (void)updateBlurEffect
@ -45,4 +49,24 @@
self.vibrancyEffectView.effect = self.vibrancyEffect; self.vibrancyEffectView.effect = self.vibrancyEffect;
} }
- (void)updateFallbackView
{
[super updateFallbackView];
if ([self useReduceTransparencyFallback]) {
for (UIView *subview in self.blurEffectView.contentView.subviews) {
[subview removeFromSuperview];
[self addSubview:subview];
}
} else {
for (UIView *subview in self.subviews) {
if (subview == self.blurEffectView) continue;
if (subview == self.reducedTransparencyFallbackView) continue;
[subview removeFromSuperview];
[self.blurEffectView.contentView addSubview:subview];
}
}
}
@end @end

View File

@ -12,5 +12,6 @@ RCT_EXPORT_MODULE();
RCT_EXPORT_VIEW_PROPERTY(blurType, NSString); RCT_EXPORT_VIEW_PROPERTY(blurType, NSString);
RCT_EXPORT_VIEW_PROPERTY(blurAmount, NSNumber); RCT_EXPORT_VIEW_PROPERTY(blurAmount, NSNumber);
RCT_EXPORT_VIEW_PROPERTY(reducedTransparencyFallbackColor, UIColor);
@end @end