Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -439,7 +439,7 @@ The blur effect on Android has always been a challenge. Therefore, version 2.0.0

On Android platforms, the component utilizes the [BlurView](https://github.com/Dimezis/BlurView) library to offer native blur effects with hardware-accelerated rendering.

For different types of `x-light`, `light`, and `dark`, the `radius` is fixed at `35` and the `downscaleFactor` is only 66% of the stated value. This is done to maintain similarity with the iOS effect.
For different types of `x-light`, `light`, and `dark`, the `radius` is fixed at `35`. This is done to maintain similarity with the iOS effect.
Comment thread
DanielAraldi marked this conversation as resolved.
Comment thread
DanielAraldi marked this conversation as resolved.

The `androidColor` property can be useful when you want to achieve a specific look or match the blur effect to other elements in your app. It **overrides** the `type` property.

Expand Down
40 changes: 20 additions & 20 deletions android/src/main/java/com/blurview/BlurOverlayColor.kt
Original file line number Diff line number Diff line change
@@ -1,50 +1,50 @@
package com.blurview

import android.content.res.Configuration
import android.graphics.Color

enum class BlurOverlayColor(val color: Int) {
X_LIGHT(Color.argb(140, 240, 240, 240)),
LIGHT(Color.argb(42, 255, 255, 255)),
DARK(Color.argb(120, 26, 22, 22)),
REGULAR(Color.argb(35, 255, 255, 255)),
PROMINENT(Color.argb(140, 240, 240, 240)),
ULTRA_THIN_MATERIAL(Color.argb(75, 240, 240, 240)),
ULTRA_THIN_MATERIAL_LIGHT(Color.argb(77, 240, 240, 240)),
REGULAR_LIGHT(Color.argb(35, 255, 255, 255)),
REGULAR_DARK(Color.argb(35, 28, 28, 30)),
PROMINENT_LIGHT(Color.argb(140, 240, 240, 240)),
PROMINENT_DARK(Color.argb(140, 28, 28, 30)),
ULTRA_THIN_MATERIAL_LIGHT(Color.argb(75, 240, 240, 240)),
ULTRA_THIN_MATERIAL_DARK(Color.argb(65, 40, 40, 40)),
THIN_MATERIAL(Color.argb(102, 240, 240, 240)),
THIN_MATERIAL_LIGHT(Color.argb(105, 240, 240, 240)),
THIN_MATERIAL_LIGHT(Color.argb(102, 240, 240, 240)),
THIN_MATERIAL_DARK(Color.argb(102, 35, 35, 35)),
MATERIAL(Color.argb(140, 245, 245, 245)),
MATERIAL_LIGHT(Color.argb(140, 248, 248, 248)),
MATERIAL_LIGHT(Color.argb(140, 245, 245, 245)),
MATERIAL_DARK(Color.argb(215, 65, 60, 60)),
THICK_MATERIAL(Color.argb(210, 248, 248, 248)),
THICK_MATERIAL_LIGHT(Color.argb(212, 248, 248, 248)),
THICK_MATERIAL_LIGHT(Color.argb(210, 248, 248, 248)),
THICK_MATERIAL_DARK(Color.argb(165, 35, 35, 35)),
CHROME_MATERIAL(Color.argb(165, 248, 248, 248)),
CHROME_MATERIAL_LIGHT(Color.argb(167, 248, 248, 248)),
CHROME_MATERIAL_LIGHT(Color.argb(165, 248, 248, 248)),
CHROME_MATERIAL_DARK(Color.argb(100, 32, 32, 32));

companion object {
fun fromString(color: String): BlurOverlayColor {
fun fromString(color: String, configuration: Configuration): BlurOverlayColor {
val isDarkMode = (configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK) == Configuration.UI_MODE_NIGHT_YES

return when (color.lowercase()) {
"x-light" -> X_LIGHT
"light" -> LIGHT
"dark" -> DARK
"regular" -> REGULAR
"prominent" -> PROMINENT
"ultra-thin-material" -> ULTRA_THIN_MATERIAL
"regular" -> if (isDarkMode) REGULAR_DARK else REGULAR_LIGHT
"prominent" -> if (isDarkMode) PROMINENT_DARK else PROMINENT_LIGHT
"ultra-thin-material" -> if (isDarkMode) ULTRA_THIN_MATERIAL_DARK else ULTRA_THIN_MATERIAL_LIGHT
"ultra-thin-material-light" -> ULTRA_THIN_MATERIAL_LIGHT
"ultra-thin-material-dark" -> ULTRA_THIN_MATERIAL_DARK
"thin-material" -> THIN_MATERIAL
"thin-material" -> if (isDarkMode) THIN_MATERIAL_DARK else THIN_MATERIAL_LIGHT
"thin-material-light" -> THIN_MATERIAL_LIGHT
"thin-material-dark" -> THIN_MATERIAL_DARK
"material" -> MATERIAL
"material" -> if (isDarkMode) MATERIAL_DARK else MATERIAL_LIGHT
"material-light" -> MATERIAL_LIGHT
"material-dark" -> MATERIAL_DARK
"thick-material" -> THICK_MATERIAL
"thick-material" -> if (isDarkMode) THICK_MATERIAL_DARK else THICK_MATERIAL_LIGHT
"thick-material-light" -> THICK_MATERIAL_LIGHT
"thick-material-dark" -> THICK_MATERIAL_DARK
"chrome-material" -> CHROME_MATERIAL
"chrome-material" -> if (isDarkMode) CHROME_MATERIAL_DARK else CHROME_MATERIAL_LIGHT
"chrome-material-light" -> CHROME_MATERIAL_LIGHT
"chrome-material-dark" -> CHROME_MATERIAL_DARK
else -> LIGHT
Expand Down
23 changes: 20 additions & 3 deletions android/src/main/java/com/blurview/BlurView.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.blurview

import android.content.Context
import android.content.res.Configuration
import android.os.Build
import android.util.AttributeSet
import android.util.Log
Expand All @@ -15,7 +16,8 @@ import com.facebook.react.uimanager.common.UIManagerType
class BlurView : eightbitlab.com.blurview.BlurView {
private var targetId: Int? = null
private var androidColor: Int? = null
private var overlayColor: BlurOverlayColor = BlurOverlayColor.fromString("light")
private var colorString: String = "light"
private var overlayColor: BlurOverlayColor = BlurOverlayColor.fromString(this.colorString, resources.configuration)
private var radius: Float = 10f * INTENSITY
private var downscaleFactor: Float = 6f
private var targetView: TargetView? = null
Expand Down Expand Up @@ -86,6 +88,20 @@ class BlurView : eightbitlab.com.blurview.BlurView {
// conflict with React Native's layout.
}

/**
* Handle configuration changes, such as dark mode or orientation changes.
* This ensures the blur view updates its overlay color based on the new
* configuration.
*/
override fun onConfigurationChanged(config: Configuration) {
super.onConfigurationChanged(config)

Comment thread
DanielAraldi marked this conversation as resolved.
val currentOverlayColor = BlurOverlayColor.fromString(this.colorString, config)
if (this.androidColor != null || currentOverlayColor == this.overlayColor) return

this.setOverlayColor(this.colorString)
}

private fun setupBlurView() {
val color = this.getColorForBlur()

Expand Down Expand Up @@ -199,11 +215,12 @@ class BlurView : eightbitlab.com.blurview.BlurView {
}

fun setOverlayColor(overlayColor: String) {
val overlay = BlurOverlayColor.fromString(overlayColor)
val overlay = BlurOverlayColor.fromString(overlayColor, resources.configuration)

this.overlayColor = overlay
this.colorString = overlayColor

if (this.androidColor != null) return;
if (this.androidColor != null) return

super.setBackgroundColor(overlay.color)
super.setOverlayColor(overlay.color)
Expand Down
4 changes: 2 additions & 2 deletions example/ios/Podfile.lock
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
PODS:
- BlurView (2.2.0):
- BlurView (2.3.1):
- DoubleConversion
- glog
- hermes-engine
Expand Down Expand Up @@ -2195,7 +2195,7 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native/ReactCommon/yoga"

SPEC CHECKSUMS:
BlurView: 1b4e4ddd595512d354f5a0c3621c6a1659462021
BlurView: 228736ad9914f6d37bb68dba81bcb667bd261716
boost: 7e761d76ca2ce687f7cc98e698152abd03a18f90
DoubleConversion: cb417026b2400c8f53ae97020b2be961b59470cb
fast_float: 06eeec4fe712a76acc9376682e4808b05ce978b6
Expand Down
14 changes: 12 additions & 2 deletions example/src/constants/blur.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,16 @@ export const NAVIGATION_ICONS = {
Settings: '⚙️',
} as const;

export const BLUR_UI_MODES = [
'regular',
'prominent',
'material',
'thin-material',
'chrome-material',
'thick-material',
'ultra-thin-material',
] as const;

export const BLUR_TYPES_DATA: BlurTypeData[] = [
{
type: 'x-light',
Expand Down Expand Up @@ -122,7 +132,7 @@ export const EFFECT_STYLES_DATA: EffectStyleData[] = [
style: 'separator',
label: 'Separator ➗',
},
];
] as const;
Comment thread
DanielAraldi marked this conversation as resolved.

export const BLUR_RADIUS_DATA: BlurRadiusData[] = [
{
Expand Down Expand Up @@ -169,4 +179,4 @@ export const BLUR_RADIUS_DATA: BlurRadiusData[] = [
radius: 100,
label: 'Blur radius 100',
},
];
] as const;
Comment thread
DanielAraldi marked this conversation as resolved.
11 changes: 8 additions & 3 deletions example/src/screens/Blurs/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,18 @@ import {
TouchableOpacity,
View,
ScrollView,
useColorScheme,
} from 'react-native';
import { BlurTarget, BlurView } from '@danielsaraldi/react-native-blur-view';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import { useBlur } from '../../hooks';
import { MOUNTAIN } from '../../assets';
import { BLUR_TYPES_DATA } from '../../constants';
import { BLUR_TYPES_DATA, BLUR_UI_MODES } from '../../constants';
import { makeStyles } from './styles';

export function Blurs() {
const targetRef = useRef<View | null>(null);
const colorScheme = useColorScheme();
const { top, bottom } = useSafeAreaInsets();
const { radius, onBlurType } = useBlur();

Expand All @@ -23,7 +25,10 @@ export function Blurs() {
const renderBlurs = useMemo(
() =>
BLUR_TYPES_DATA.map(({ type, label }) => {
const color = type.includes('dark') ? 'white' : 'black';
const colorByType = type.includes('dark') ? 'white' : 'black';
const isDarkMode = colorScheme === 'dark';
const isUIMode = BLUR_UI_MODES.some((mode) => type === mode);
const color = isUIMode ? (isDarkMode ? 'white' : 'black') : colorByType;

return (
<TouchableOpacity
Expand All @@ -43,7 +48,7 @@ export function Blurs() {
</TouchableOpacity>
);
}),
[radius, styles, onBlurType]
[radius, styles, colorScheme, onBlurType]
);

return (
Expand Down
16 changes: 8 additions & 8 deletions example/src/screens/Settings/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
ScrollView,
Text,
TouchableOpacity,
useColorScheme,
View,
} from 'react-native';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
Expand All @@ -22,7 +23,7 @@ import Animated, {
} from 'react-native-reanimated';
import { useBlur } from '../../hooks';
import { PORSCHE_ARCHITECTURE } from '../../assets';
import { BLUR_RADIUS_DATA } from '../../constants';
import { BLUR_RADIUS_DATA, BLUR_UI_MODES } from '../../constants';
import { makeStyles } from './styles';
import { isIos } from '../../utils';

Expand All @@ -34,12 +35,16 @@ export function Settings() {

const targetRef = useRef<View | null>(null);
const scrollTargetRef = useRef<View | null>(null);
const colorScheme = useColorScheme();
const { top, bottom } = useSafeAreaInsets();
const { blurType, effectStyle, radius, isDark, onRadius } = useBlur();
Comment thread
DanielAraldi marked this conversation as resolved.

const radiusAnimation = useSharedValue(0.01);

const color = blurType.includes('dark') ? 'white' : 'black';
const colorByType = blurType.includes('dark') ? 'white' : 'black';
const isDarkMode = colorScheme === 'dark';
const isUIMode = BLUR_UI_MODES.some((mode) => blurType === mode);
const color = isUIMode ? (isDarkMode ? 'white' : 'black') : colorByType;
const defaultMessage = isIos
? 'Default blur type is light, radius is 10 and vibrancy effect style is label.'
: 'Default blur type is light and default radius is 10.';
Expand Down Expand Up @@ -109,12 +114,7 @@ export function Settings() {
style={styles.absoluteFill}
/>

<Text
style={[
styles.configurationText,
isDark && styles.configurationTextDark,
]}
>
<Text style={[styles.configurationText, { color }]}>
Explore radius and type configurations to customize the blur
effect ✨{'\n'}Adjust the settings to see how they impact the
appearance of the blur on both Android and iOS platforms 🌫️
Expand Down
26 changes: 20 additions & 6 deletions example/src/screens/Vibrancies/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
ScrollView,
Text,
TouchableOpacity,
useColorScheme,
View,
} from 'react-native';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
Expand All @@ -13,19 +14,32 @@ import {
} from '@danielsaraldi/react-native-blur-view';
import { useBlur } from '../../hooks';
import { PORSCHE_MOUNTAIN } from '../../assets';
import { BLUR_TYPES_DATA, EFFECT_STYLES_DATA } from '../../constants';
import {
BLUR_TYPES_DATA,
BLUR_UI_MODES,
EFFECT_STYLES_DATA,
} from '../../constants';
import { makeStyles } from './styles';

export function Vibrancies() {
const colorScheme = useColorScheme();
const { radius, blurType, effectStyle, onBlurType, onEffectStyle } =
useBlur();
const { top, bottom } = useSafeAreaInsets();

const getTextColor = useCallback((type: BlurType) => {
const exceptions = ['x-light', 'light', 'dark', 'regular', 'prominent'];
const color = type.includes('dark') ? 'white' : 'black';
return exceptions.some((exception) => exception === type) ? 'white' : color;
}, []);
const getTextColor = useCallback(
(type: BlurType) => {
const exceptions = ['x-light', 'light', 'dark', 'regular', 'prominent'];
const isException = exceptions.some((exception) => exception === type);
if (isException) return 'white';

const isDarkMode = colorScheme === 'dark';
const isUIMode = BLUR_UI_MODES.some((mode) => type === mode);
const colorByType = type.includes('dark') ? 'white' : 'black';
return isUIMode ? (isDarkMode ? 'white' : 'black') : colorByType;
Comment thread
DanielAraldi marked this conversation as resolved.
},
[colorScheme]
);

const styles = useMemo(() => makeStyles({ top, bottom }), [top, bottom]);

Expand Down
2 changes: 1 addition & 1 deletion src/BlurTarget.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import type { BlurTargetProps } from './@types';
* import { styles } from './styles';
*
* const MyComponent = () => {
* const blurTargetRef = useRef(null);
* const blurTargetRef = useRef<View | null>(null);
*
* return (
* <View style={styles.container}>
Expand Down
14 changes: 6 additions & 8 deletions src/BlurView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import { globalStyles } from './styles';
* import { styles } from './styles';
*
* const MyComponent = () => {
* const blurTargetRef = useRef(null);
* const blurTargetRef = useRef<View | null>(null);
*
* return (
* <View style={styles.container}>
Expand Down Expand Up @@ -69,20 +69,19 @@ export const BlurView = forwardRef<View, BlurViewProps>((props, ref) => {
const commonProps = useMemo(() => {
const isPrimary = type === 'x-light' || type === 'light' || type === 'dark';
const _radius = isPrimary ? radius : 35;
Comment thread
DanielAraldi marked this conversation as resolved.
const _downscaleFactor = isPrimary
? downscaleFactor
: downscaleFactor * 0.66;

return {
ref,
androidColor,
downscaleFactor,
targetId: isAndroid ? targetId : undefined,
reducedTransparencyFallbackColor,
downscaleFactor: _downscaleFactor,
overlayColor: type,
radius: isAndroid ? _radius : radius,
...rest,
};
}, [
ref,
type,
radius,
downscaleFactor,
Expand All @@ -102,7 +101,6 @@ export const BlurView = forwardRef<View, BlurViewProps>((props, ref) => {
return (
<View style={[globalStyles.container, style]}>
<Blur
ref={ref}
style={[globalStyles.absoluteFill, backgroundColor]}
{...commonProps}
/>
Expand All @@ -115,14 +113,14 @@ export const BlurView = forwardRef<View, BlurViewProps>((props, ref) => {
style={[globalStyles.container, style, !isAndroid && backgroundColor]}
>
{isAndroid ? (
<Blur ref={ref} style={globalStyles.absoluteFill} {...commonProps}>
<Blur style={globalStyles.absoluteFill} {...commonProps}>
<View style={[globalStyles.content, style, backgroundColor]}>
{children}
</View>
</Blur>
) : (
<>
<Blur ref={ref} style={globalStyles.absoluteFill} {...commonProps} />
<Blur style={globalStyles.absoluteFill} {...commonProps} />

{children}
</>
Expand Down
Loading