Merge pull request #330 from adkenyon/a11y-fallback-for-reduce-transparency
Fallback background color for A11y reduce transparency
This commit is contained in:
commit
fa4711bf4d
|
@ -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.
|
||||
- `blurAmount` (Default: 10, Number)
|
||||
- `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.
|
||||
|
||||
|
@ -122,6 +124,7 @@ export default class Menu extends Component {
|
|||
viewRef={this.state.viewRef}
|
||||
blurType="light"
|
||||
blurAmount={10}
|
||||
reducedTransparencyFallbackColor="white"
|
||||
/>
|
||||
<Text>I'm the non blurred text because I got rendered on top of the BlurView</Text>
|
||||
</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.
|
||||
|
||||
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
|
||||
|
||||
**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
|
||||
|
||||
|
|
|
@ -60,6 +60,7 @@ export default class Basic extends Component {
|
|||
<BlurView
|
||||
blurType={this.state.blurBlurType}
|
||||
blurAmount={100}
|
||||
reducedTransparencyFallbackColor={'pink'}
|
||||
style={[styles.blurView]}>
|
||||
<Text style={[styles.text, { color: tintColor }]}>
|
||||
Blur component ({platform})
|
||||
|
@ -84,6 +85,7 @@ export default class Basic extends Component {
|
|||
<VibrancyView
|
||||
blurType={this.state.vibrancyBlurType}
|
||||
blurAmount={10}
|
||||
reducedTransparencyFallbackColor={'pink'}
|
||||
style={[styles.container, styles.blurContainer]}>
|
||||
|
||||
<Text style={styles.text}>
|
||||
|
|
|
@ -2,7 +2,7 @@ import * as React from "react";
|
|||
import { StyleProp, ViewStyle } from "react-native";
|
||||
|
||||
export interface BlurViewProperties {
|
||||
blurType:
|
||||
blurType?:
|
||||
| "xlight"
|
||||
| "light"
|
||||
| "dark"
|
||||
|
@ -28,6 +28,7 @@ export interface BlurViewProperties {
|
|||
// tvOS only
|
||||
| "extraDark"
|
||||
blurAmount?: number // 0 - 100
|
||||
reducedTransparencyFallbackColor?: string
|
||||
style?: StyleProp<ViewStyle>
|
||||
blurRadius?: number
|
||||
downsampleFactor?: number
|
||||
|
|
|
@ -33,8 +33,9 @@ export type BlurType =
|
|||
| 'extraDark';
|
||||
|
||||
export type BlurViewProps = {
|
||||
blurType: BlurType,
|
||||
blurAmount: number, // 0 - 100
|
||||
blurType?: BlurType,
|
||||
blurAmount?: number, // 0 - 100,
|
||||
reducedTransparencyFallbackColor?: String,
|
||||
style?: ?ViewStyleProp,
|
||||
};
|
||||
|
||||
|
|
|
@ -3,11 +3,15 @@
|
|||
|
||||
@interface BlurView : UIView
|
||||
|
||||
@property (nonatomic, copy) NSString *blurType;
|
||||
@property (nonatomic, copy) NSNumber *blurAmount;
|
||||
@property (nonatomic, copy, nullable) NSString *blurType;
|
||||
@property (nonatomic, copy, nullable) NSNumber *blurAmount;
|
||||
@property (nonatomic, copy, nullable) UIColor *reducedTransparencyFallbackColor;
|
||||
|
||||
@property (nonatomic, strong) BlurEffectWithAmount *blurEffect;
|
||||
@property (nonatomic, strong) UIVisualEffectView *blurEffectView;
|
||||
@property (nonatomic, strong, nullable) BlurEffectWithAmount *blurEffect;
|
||||
@property (nonatomic, strong, nullable) UIVisualEffectView *blurEffectView;
|
||||
@property (nonatomic, strong, nullable) UIView *reducedTransparencyFallbackView;
|
||||
|
||||
- (void)updateBlurEffect;
|
||||
- (void)updateFallbackView;
|
||||
- (BOOL)useReduceTransparencyFallback;
|
||||
@end
|
||||
|
|
|
@ -7,15 +7,33 @@
|
|||
|
||||
@implementation BlurView
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame {
|
||||
- (instancetype)init
|
||||
{
|
||||
if (self = [super init]) {
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(reduceTransparencyStatusDidChange:)
|
||||
name:UIAccessibilityReduceTransparencyStatusDidChangeNotification
|
||||
object:nil];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame
|
||||
{
|
||||
if (self = [super initWithFrame:frame]) {
|
||||
self.blurEffectView = [[UIVisualEffectView alloc] init];
|
||||
self.blurEffectView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
|
||||
self.blurEffectView.frame = frame;
|
||||
|
||||
self.reducedTransparencyFallbackView = [[UIView alloc] init];
|
||||
self.reducedTransparencyFallbackView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
|
||||
self.reducedTransparencyFallbackView.frame = frame;
|
||||
|
||||
self.blurAmount = @10;
|
||||
self.blurType = @"dark";
|
||||
[self updateBlurEffect];
|
||||
[self updateFallbackView];
|
||||
|
||||
self.clipsToBounds = true;
|
||||
|
||||
|
@ -25,10 +43,16 @@
|
|||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
||||
}
|
||||
|
||||
- (void)layoutSubviews
|
||||
{
|
||||
[super layoutSubviews];
|
||||
self.blurEffectView.frame = self.bounds;
|
||||
self.reducedTransparencyFallbackView.frame = self.bounds;
|
||||
}
|
||||
|
||||
- (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
|
||||
{
|
||||
|
@ -89,6 +120,11 @@
|
|||
return UIBlurEffectStyleDark;
|
||||
}
|
||||
|
||||
- (BOOL)useReduceTransparencyFallback
|
||||
{
|
||||
return UIAccessibilityIsReduceTransparencyEnabled() == YES && self.reducedTransparencyFallbackColor != NULL;
|
||||
}
|
||||
|
||||
- (void)updateBlurEffect
|
||||
{
|
||||
UIBlurEffectStyle style = [self blurEffectStyle];
|
||||
|
@ -96,4 +132,32 @@
|
|||
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
|
||||
|
|
|
@ -12,5 +12,6 @@ RCT_EXPORT_MODULE();
|
|||
|
||||
RCT_EXPORT_VIEW_PROPERTY(blurType, NSString);
|
||||
RCT_EXPORT_VIEW_PROPERTY(blurAmount, NSNumber);
|
||||
RCT_EXPORT_VIEW_PROPERTY(reducedTransparencyFallbackColor, UIColor);
|
||||
|
||||
@end
|
||||
|
|
|
@ -30,8 +30,12 @@
|
|||
}
|
||||
|
||||
- (void)insertReactSubview:(id<RCTComponent>)subview atIndex:(NSInteger)atIndex {
|
||||
if ([self useReduceTransparencyFallback]) {
|
||||
[self addSubview:(UIView*)subview];
|
||||
} else {
|
||||
[self.vibrancyEffectView.contentView addSubview:(UIView*)subview];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)updateBlurEffect
|
||||
{
|
||||
|
@ -45,4 +49,24 @@
|
|||
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
|
||||
|
|
|
@ -12,5 +12,6 @@ RCT_EXPORT_MODULE();
|
|||
|
||||
RCT_EXPORT_VIEW_PROPERTY(blurType, NSString);
|
||||
RCT_EXPORT_VIEW_PROPERTY(blurAmount, NSNumber);
|
||||
RCT_EXPORT_VIEW_PROPERTY(reducedTransparencyFallbackColor, UIColor);
|
||||
|
||||
@end
|
||||
|
|
Loading…
Reference in New Issue