Newby Coder header banner

React Native Blurred Overlay

Blur Background in React Native

To blur background in React Native, BlurView component from @react-native-community/blur module can be used

Provided example is of a simple screen with a switch to show different types of blur effects

BlurView component

<BlurView
    viewRef={this.state.viewRef}
    style={styles.blurView}
    blurRadius={1}
    blurType={this.state.blurType}
    // The following props are also available on Android:
    // blurRadius={20}
    // downsampleFactor={10}
    // overlayColor={'rgba(0, 0, 255, .6)'}   // set a blue overlay
/>

Types of blur effect :

viewRef

viewRef is a node handler for a specific React component

A reference to a view is set as a string value to ref property of a component

<View style={styles.innerContainer} ref={'backgroundView'}>

This reference is accessed by using refs property of React component class

this.refs.backgroundView

The corresponding node handler can then be retrieved by using findNoneHandle() function for the reference, after the component is loaded into DOM tree

 imageLoaded() {
    this.setState({ viewRef: findNodeHandle(this.refs.backgroundView) });
}
...
//Inside render function
<Image
    source={{uri: 'https://images.freeimages.com/images/large-previews/a0d/autumn-tree-1382832.jpg'}}
    style={styles.image}
    onLoadEnd={this.imageLoaded.bind(this)} />
    
Import
import { BlurView } from '@react-native-community/blur';

Creating new React Native App

Check React Native Installation for installation related info

Use react-native init command to create a new React Native project (here named NcBlurApp)

react-native init NcBlurApp

This creates a directory named NcBlurApp and initializes it as a react native application directory

This can be skipped in case an existing react native project is being integrated into


Dependency

Go to project directory (here NcBlurApp)

cd NcBlurApp

Add @react-native-community/blur package to current project using yarn

yarn add @react-native-community/blur

or using npm

npm install @react-native-community/blur --save

iOS

After adding dependency, cd into ios folder inside project directory

cd ios

Use pod command to install any required CocoaPods dependencies:

pod install

App Code

App.js
import React, { Component } from 'react';

import {
  Image,
  InteractionManager,
  StyleSheet,
  Switch,
  Text,
  View,
  ScrollView,
  TouchableOpacity,
  findNodeHandle,
} from 'react-native';

import { BlurView } from '@react-native-community/blur';

export default class Basic extends Component {
  constructor() {
    super();
    this.state = {
      showBlur: false,
      viewRef: null,
      blurType: 'light',
      blur_counter: 0,
      render_counter: 0,
    };
  }

  imageLoaded() {
    // Workaround for race condition on initial load
    InteractionManager.runAfterInteractions(() => {
      setTimeout(() => {
        this.setState({ viewRef: findNodeHandle(this.refs.backgroundView) });
      }, 500);
    });
  }

  setBackgroundXlight() {
    this.setState({
      blurType: 'xlight',
    });
  }
  setBackgroundLight() {
    this.setState({
      blurType: 'light',
    });
  }
  setBackgroundDark() {
    this.setState({
      blurType: 'dark',
    });
  }

  renderBlurView() {
    this.state.blur_counter++;
    //For the text color on change of the background
    const textColor = ['#ffffff', '#000000'];
    if (this.state.blurType === 'xlight') {textColor.reverse();}

    return (

      <View style={{flexDirection: 'column',justifyContent: 'flex-end',}}>
       {this.state.viewRef && <BlurView
          viewRef={this.state.viewRef}
          style={{position: 'absolute', left: 0, top: 0, bottom: 0, right: 0, zIndex:1, }}
          blurRadius={2}
          blurType={this.state.blurType}
          // downsampleFactor={10}
          // overlayColor={'rgba(0, 0, 255, .6)'}   // set a blue overlay
        />}
        <View style={{
          flex: 1,
          flexDirection: 'column',
          justifyContent: 'flex-end',
          paddingBottom:32,
        }}>
          <Text style={[styles.text, { color: textColor[0] }]}>
            Blur component
          </Text>
          <TouchableOpacity
              style={styles.button}
              onPress={this.setBackgroundXlight.bind(this)}>
            <Text style={[styles.text, { color: textColor[0] }]}>xlight</Text>
          </TouchableOpacity>
          <TouchableOpacity
              style={styles.button}
              onPress={this.setBackgroundLight.bind(this)}>
            <Text style={[styles.text, { color: textColor[0] }]}>light</Text>
          </TouchableOpacity>
          <TouchableOpacity
              style={styles.button}
              onPress={this.setBackgroundDark.bind(this)}>
            <Text style={[styles.text, { color: textColor[0] }]}>dark</Text>
          </TouchableOpacity>
        </View>
      </View>
    );
  }

  render() {
    this.state.render_counter++;
    const textColor = ['#ffffff', '#000000'];
    if (this.state.blurType === 'xlight') { textColor.reverse();}
    return (
      <View style={styles.outerContainer}>
        <View style={styles.innerContainer} ref={'backgroundView'}>
          <Image
            source={{uri: 'https://images.freeimages.com/images/large-previews/a0d/autumn-tree-1382832.jpg'}}
            style={styles.image}
            onLoadEnd={this.imageLoaded.bind(this)} />
          <View
            style={styles.blurSwitchView}>
            <Text style={[styles.text, { color: textColor[0] }]}>Show Blur Background : </Text>
            <Text style={[styles.text, { color: textColor[0] }]}>{this.state.showBlur ? "Yes" : "No"}</Text>
            <Text style={[styles.text, { color: textColor[0] }]}>Blur counter {this.state.blur_counter} Render counter {this.state.render_counter}</Text>
            <Switch
              onValueChange={(value) => this.setState({showBlur: value})}
              value={this.state.showBlur} />
          </View>
        </View>
        { this.state.showBlur ? this.renderBlurView() : null }
      </View>
    );
  }
}

const styles = StyleSheet.create({
  innerContainer: {
    flex:1,
    justifyContent: 'center',
    alignItems: 'center',
    position:'absolute',
    top:0,
    left:0,
    right:0,
    bottom:0,
    zIndex:0,
  },
  outerContainer: {
    justifyContent: 'center',
    alignItems: 'center',
    position:'absolute',
    top:0,
    left:0,
    right:0,
    bottom:0,
  },
  image: {
    position: 'absolute',
    alignSelf:'stretch',
    left: 0,
    top: 0,
    bottom: 0,
    right: 0,
    zIndex: 0,
  },
  text: {
    fontSize: 22,
    fontWeight: 'bold',
    textAlign: 'center',
    margin: 10,
    color:"#d0d0d0"
  },
  blurSwitchView: {
    position: 'absolute',
    top: 30,
    alignItems: 'center',
    zIndex: 1,
  },
  button: {
    alignItems: 'center',
    backgroundColor: 'lightgreen',
    width:250,
    marginLeft:100,
    marginRight:100,
    marginTop:16
  },
});

Run instructions

Running in Android

cd into project directory (here NcBlurApp)

cd NcBlurApp

Run metro server to serve js

react-native start

Go to project directory in another terminal tab

Enter following run command for Android:

react-native run-android
cl-react-native-blur-background

Running in ios

cd into project directory (here NcBlurApp)

cd NcBlurApp

Enter following command :

react-native run-ios

This might take some time


If the app shows error about metro server not configured (check Running an App in iOS), then run metro server in another tab:

react-native start

Reload the app

Re-run react-native run-ios command if reloading doesn't work

cm-react-native-blur-background-as1cm-react-native-blur-background-as2cm-react-native-blur-background-as3