Skip to content

Commit fa4711b

Browse files
authored
Merge pull request Kureev#330 from adkenyon/a11y-fallback-for-reduce-transparency
Fallback background color for A11y reduce transparency
2 parents 4293c00 + 584f601 commit fa4711b

File tree

9 files changed

+123
-20
lines changed

9 files changed

+123
-20
lines changed

README.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,8 @@ import { BlurView, VibrancyView } from "@react-native-community/blur";
9595
- `ultraThinMaterialLight` - An adaptable blur effect that creates the appearance of an ultra-thin material.
9696
- `blurAmount` (Default: 10, Number)
9797
- `0-100` - Adjusts blur intensity
98+
- `reducedTransparencyFallbackColor` (Color) (iOS only)
99+
- `black, white, #rrggbb, etc` - background color to use if accessibility setting ReduceTransparency is enabled
98100

99101
> Note: The maximum `blurAmount` on Android is 32, so higher values will be clamped to 32.
100102
@@ -122,6 +124,7 @@ export default class Menu extends Component {
122124
viewRef={this.state.viewRef}
123125
blurType="light"
124126
blurAmount={10}
127+
reducedTransparencyFallbackColor="white"
125128
/>
126129
<Text>I'm the non blurred text because I got rendered on top of the BlurView</Text>
127130
</View>
@@ -146,9 +149,11 @@ const styles = StyleSheet.create({
146149
147150
In this example, the `Image` component will be blurred, because the `BlurView` in positioned on top. But the `Text` will stay unblurred.
148151
152+
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`)
153+
149154
### VibrancyView
150155

151-
**Uses the same properties as `BlurView` (`blurType` and `blurAmount`).**
156+
**Uses the same properties as `BlurView` (`blurType`, `blurAmount`, and `reducedTransparencyFallbackColor`).**
152157

153158
> The vibrancy effect lets the content underneath a blurred view show through more vibrantly
154159

example/App.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ export default class Basic extends Component {
6060
<BlurView
6161
blurType={this.state.blurBlurType}
6262
blurAmount={100}
63+
reducedTransparencyFallbackColor={'pink'}
6364
style={[styles.blurView]}>
6465
<Text style={[styles.text, { color: tintColor }]}>
6566
Blur component ({platform})
@@ -84,6 +85,7 @@ export default class Basic extends Component {
8485
<VibrancyView
8586
blurType={this.state.vibrancyBlurType}
8687
blurAmount={10}
88+
reducedTransparencyFallbackColor={'pink'}
8789
style={[styles.container, styles.blurContainer]}>
8890

8991
<Text style={styles.text}>

index.d.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import * as React from "react";
22
import { StyleProp, ViewStyle } from "react-native";
33

44
export interface BlurViewProperties {
5-
blurType:
5+
blurType?:
66
| "xlight"
77
| "light"
88
| "dark"
@@ -28,6 +28,7 @@ export interface BlurViewProperties {
2828
// tvOS only
2929
| "extraDark"
3030
blurAmount?: number // 0 - 100
31+
reducedTransparencyFallbackColor?: string
3132
style?: StyleProp<ViewStyle>
3233
blurRadius?: number
3334
downsampleFactor?: number

index.js.flow

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,9 @@ export type BlurType =
3333
| 'extraDark';
3434

3535
export type BlurViewProps = {
36-
blurType: BlurType,
37-
blurAmount: number, // 0 - 100
36+
blurType?: BlurType,
37+
blurAmount?: number, // 0 - 100,
38+
reducedTransparencyFallbackColor?: String,
3839
style?: ?ViewStyleProp,
3940
};
4041

ios/BlurView.h

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,15 @@
33

44
@interface BlurView : UIView
55

6-
@property (nonatomic, copy) NSString *blurType;
7-
@property (nonatomic, copy) NSNumber *blurAmount;
6+
@property (nonatomic, copy, nullable) NSString *blurType;
7+
@property (nonatomic, copy, nullable) NSNumber *blurAmount;
8+
@property (nonatomic, copy, nullable) UIColor *reducedTransparencyFallbackColor;
89

9-
@property (nonatomic, strong) BlurEffectWithAmount *blurEffect;
10-
@property (nonatomic, strong) UIVisualEffectView *blurEffectView;
10+
@property (nonatomic, strong, nullable) BlurEffectWithAmount *blurEffect;
11+
@property (nonatomic, strong, nullable) UIVisualEffectView *blurEffectView;
12+
@property (nonatomic, strong, nullable) UIView *reducedTransparencyFallbackView;
1113

1214
- (void)updateBlurEffect;
15+
- (void)updateFallbackView;
16+
- (BOOL)useReduceTransparencyFallback;
1317
@end

ios/BlurView.m

Lines changed: 76 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,28 +7,52 @@ @interface BlurView ()
77

88
@implementation BlurView
99

10-
- (instancetype)initWithFrame:(CGRect)frame {
11-
if (self = [super initWithFrame:frame]) {
12-
self.blurEffectView = [[UIVisualEffectView alloc] init];
13-
self.blurEffectView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
14-
self.blurEffectView.frame = frame;
10+
- (instancetype)init
11+
{
12+
if (self = [super init]) {
13+
[[NSNotificationCenter defaultCenter] addObserver:self
14+
selector:@selector(reduceTransparencyStatusDidChange:)
15+
name:UIAccessibilityReduceTransparencyStatusDidChangeNotification
16+
object:nil];
17+
}
1518

16-
self.blurAmount = @10;
17-
self.blurType = @"dark";
18-
[self updateBlurEffect];
19+
return self;
20+
}
1921

20-
self.clipsToBounds = true;
22+
- (instancetype)initWithFrame:(CGRect)frame
23+
{
24+
if (self = [super initWithFrame:frame]) {
25+
self.blurEffectView = [[UIVisualEffectView alloc] init];
26+
self.blurEffectView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
27+
self.blurEffectView.frame = frame;
2128

22-
[self addSubview:self.blurEffectView];
23-
}
29+
self.reducedTransparencyFallbackView = [[UIView alloc] init];
30+
self.reducedTransparencyFallbackView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
31+
self.reducedTransparencyFallbackView.frame = frame;
2432

25-
return self;
33+
self.blurAmount = @10;
34+
self.blurType = @"dark";
35+
[self updateBlurEffect];
36+
[self updateFallbackView];
37+
38+
self.clipsToBounds = true;
39+
40+
[self addSubview:self.blurEffectView];
41+
}
42+
43+
return self;
44+
}
45+
46+
- (void)dealloc
47+
{
48+
[[NSNotificationCenter defaultCenter] removeObserver:self];
2649
}
2750

2851
- (void)layoutSubviews
2952
{
3053
[super layoutSubviews];
3154
self.blurEffectView.frame = self.bounds;
55+
self.reducedTransparencyFallbackView.frame = self.bounds;
3256
}
3357

3458
- (void)setBlurType:(NSString *)blurType
@@ -47,6 +71,13 @@ - (void)setBlurAmount:(NSNumber *)blurAmount
4771
}
4872
}
4973

74+
- (void)setReducedTransparencyFallbackColor:(nullable UIColor *)reducedTransparencyFallbackColor
75+
{
76+
if (reducedTransparencyFallbackColor && ![self.reducedTransparencyFallbackColor isEqual:reducedTransparencyFallbackColor]) {
77+
_reducedTransparencyFallbackColor = reducedTransparencyFallbackColor;
78+
[self updateFallbackView];
79+
}
80+
}
5081

5182
- (UIBlurEffectStyle)blurEffectStyle
5283
{
@@ -89,11 +120,44 @@ - (UIBlurEffectStyle)blurEffectStyle
89120
return UIBlurEffectStyleDark;
90121
}
91122

123+
- (BOOL)useReduceTransparencyFallback
124+
{
125+
return UIAccessibilityIsReduceTransparencyEnabled() == YES && self.reducedTransparencyFallbackColor != NULL;
126+
}
127+
92128
- (void)updateBlurEffect
93129
{
94130
UIBlurEffectStyle style = [self blurEffectStyle];
95131
self.blurEffect = [BlurEffectWithAmount effectWithStyle:style andBlurAmount:self.blurAmount];
96132
self.blurEffectView.effect = self.blurEffect;
97133
}
98134

135+
- (void)updateFallbackView
136+
{
137+
if ([self useReduceTransparencyFallback]) {
138+
if (![self.subviews containsObject:self.reducedTransparencyFallbackView]) {
139+
[self insertSubview:self.reducedTransparencyFallbackView atIndex:0];
140+
}
141+
142+
if ([self.subviews containsObject:self.blurEffectView]) {
143+
[self.blurEffectView removeFromSuperview];
144+
}
145+
} else {
146+
if ([self.subviews containsObject:self.reducedTransparencyFallbackView]) {
147+
[self.reducedTransparencyFallbackView removeFromSuperview];
148+
}
149+
150+
if (![self.subviews containsObject:self.blurEffectView]) {
151+
[self insertSubview:self.blurEffectView atIndex:0];
152+
}
153+
}
154+
155+
self.reducedTransparencyFallbackView.backgroundColor = self.reducedTransparencyFallbackColor;
156+
}
157+
158+
- (void)reduceTransparencyStatusDidChange:(__unused NSNotification *)notification
159+
{
160+
[self updateFallbackView];
161+
}
162+
99163
@end

ios/BlurViewManager.m

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,6 @@ - (UIView *)view
1212

1313
RCT_EXPORT_VIEW_PROPERTY(blurType, NSString);
1414
RCT_EXPORT_VIEW_PROPERTY(blurAmount, NSNumber);
15+
RCT_EXPORT_VIEW_PROPERTY(reducedTransparencyFallbackColor, UIColor);
1516

1617
@end

ios/VibrancyView.m

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,11 @@ - (void)layoutSubviews
3030
}
3131

3232
- (void)insertReactSubview:(id<RCTComponent>)subview atIndex:(NSInteger)atIndex {
33+
if ([self useReduceTransparencyFallback]) {
34+
[self addSubview:(UIView*)subview];
35+
} else {
3336
[self.vibrancyEffectView.contentView addSubview:(UIView*)subview];
37+
}
3438
}
3539

3640
- (void)updateBlurEffect
@@ -45,4 +49,24 @@ - (void)updateVibrancyEffect
4549
self.vibrancyEffectView.effect = self.vibrancyEffect;
4650
}
4751

52+
- (void)updateFallbackView
53+
{
54+
[super updateFallbackView];
55+
56+
if ([self useReduceTransparencyFallback]) {
57+
for (UIView *subview in self.blurEffectView.contentView.subviews) {
58+
[subview removeFromSuperview];
59+
[self addSubview:subview];
60+
}
61+
} else {
62+
for (UIView *subview in self.subviews) {
63+
if (subview == self.blurEffectView) continue;
64+
if (subview == self.reducedTransparencyFallbackView) continue;
65+
66+
[subview removeFromSuperview];
67+
[self.blurEffectView.contentView addSubview:subview];
68+
}
69+
}
70+
}
71+
4872
@end

ios/VibrancyViewManager.m

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,6 @@ - (UIView *)view
1212

1313
RCT_EXPORT_VIEW_PROPERTY(blurType, NSString);
1414
RCT_EXPORT_VIEW_PROPERTY(blurAmount, NSNumber);
15+
RCT_EXPORT_VIEW_PROPERTY(reducedTransparencyFallbackColor, UIColor);
1516

1617
@end

0 commit comments

Comments
 (0)