From 4518b13efed0b0c3d572133f766f10858178080f Mon Sep 17 00:00:00 2001 From: Alan Kenyon Date: Tue, 20 Aug 2019 23:19:31 -0700 Subject: [PATCH 1/3] working fallback view with background color --- example/App.js | 2 + ios/BlurView.h | 12 ++++-- ios/BlurView.m | 88 +++++++++++++++++++++++++++++++++------ ios/BlurViewManager.m | 1 + ios/VibrancyView.m | 24 +++++++++++ ios/VibrancyViewManager.m | 1 + 6 files changed, 112 insertions(+), 16 deletions(-) diff --git a/example/App.js b/example/App.js index ad738c0..a22e88b 100644 --- a/example/App.js +++ b/example/App.js @@ -60,6 +60,7 @@ export default class Basic extends Component { Blur component ({platform}) @@ -84,6 +85,7 @@ export default class Basic extends Component { diff --git a/ios/BlurView.h b/ios/BlurView.h index 93d693a..7c09d68 100644 --- a/ios/BlurView.h +++ b/ios/BlurView.h @@ -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 diff --git a/ios/BlurView.m b/ios/BlurView.m index 7372166..f333d8d 100644 --- a/ios/BlurView.m +++ b/ios/BlurView.m @@ -7,28 +7,52 @@ @implementation BlurView -- (instancetype)initWithFrame:(CGRect)frame { - if (self = [super initWithFrame:frame]) { - self.blurEffectView = [[UIVisualEffectView alloc] init]; - self.blurEffectView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; - self.blurEffectView.frame = frame; +- (instancetype)init +{ + if (self = [super init]) { + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(reduceTransparencyStatusDidChange:) + name:UIAccessibilityReduceTransparencyStatusDidChangeNotification + object:nil]; + } - self.blurAmount = @10; - self.blurType = @"dark"; - [self updateBlurEffect]; + return self; +} - 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 { [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 diff --git a/ios/BlurViewManager.m b/ios/BlurViewManager.m index 991a562..de58e0c 100644 --- a/ios/BlurViewManager.m +++ b/ios/BlurViewManager.m @@ -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 diff --git a/ios/VibrancyView.m b/ios/VibrancyView.m index 4cbca84..71401e3 100644 --- a/ios/VibrancyView.m +++ b/ios/VibrancyView.m @@ -30,7 +30,11 @@ } - (void)insertReactSubview:(id)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 diff --git a/ios/VibrancyViewManager.m b/ios/VibrancyViewManager.m index f050490..17bb10e 100644 --- a/ios/VibrancyViewManager.m +++ b/ios/VibrancyViewManager.m @@ -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 From bd54c4c87c6d08344efe73d133eee1f3eda567a0 Mon Sep 17 00:00:00 2001 From: Alan Kenyon Date: Wed, 21 Aug 2019 08:41:37 -0700 Subject: [PATCH 2/3] readme update --- README.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index d1d2667..45febe6 100644 --- a/README.md +++ b/README.md @@ -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" /> I'm the non blurred text because I got rendered on top of the BlurView @@ -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 From 584f6014f0949b853586864515b7f4f63199fbcf Mon Sep 17 00:00:00 2001 From: Alan Kenyon Date: Wed, 21 Aug 2019 09:16:06 -0700 Subject: [PATCH 3/3] type checks --- index.d.ts | 3 ++- index.js.flow | 5 +++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/index.d.ts b/index.d.ts index d5890b4..968b379 100644 --- a/index.d.ts +++ b/index.d.ts @@ -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 blurRadius?: number downsampleFactor?: number diff --git a/index.js.flow b/index.js.flow index 4fc38a9..e6319d6 100644 --- a/index.js.flow +++ b/index.js.flow @@ -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, };