You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Native中能否自定义模糊组件?替代@react-native-community/blur

实现替代@react-native-community/blur的跨平台自定义模糊组件

当然可以。针对@react-native-community/blur在Android端强制全屏、不遵循布局约束的问题,我们可以分平台定制实现:iOS复用原包的稳定逻辑,Android通过原生自定义View实现支持约束布局的模糊效果。

实现步骤

1. Android原生自定义BlurView

创建支持动态模糊半径、遵循布局约束的原生View,分别适配Android 12+的RenderEffect和低版本的RenderScript:

// BlurView.java
package com.your.app.package;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.RenderEffect;
import android.graphics.Shader;
import android.os.Build;
import android.util.AttributeSet;
import android.view.View;
import androidx.annotation.RequiresApi;
import androidx.appcompat.widget.AppCompatView;
import androidx.renderscript.Allocation;
import androidx.renderscript.Element;
import androidx.renderscript.RenderScript;
import androidx.renderscript.ScriptIntrinsicBlur;

public class BlurView extends AppCompatView {
    private int blurRadius = 10;
    private boolean isDirty = true;

    public BlurView(Context context) {
        super(context);
        init();
    }

    public BlurView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public BlurView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        setWillNotDraw(false);
        setLayerType(View.LAYER_TYPE_HARDWARE, null);
    }

    public void setBlurRadius(int radius) {
        if (blurRadius != radius) {
            blurRadius = radius;
            isDirty = true;
            invalidate();
        }
    }

    @Override
    protected void onDraw(Canvas canvas) {
        if (isDirty) {
            updateBlur();
            isDirty = false;
        }
        super.onDraw(canvas);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        isDirty = true;
    }

    @RequiresApi(api = Build.VERSION_CODES.S)
    private void applyRenderEffect() {
        RenderEffect blurEffect = RenderEffect.createBlurEffect(blurRadius, blurRadius, Shader.TileMode.CLAMP);
        setRenderEffect(blurEffect);
    }

    private void applyRenderScriptBlur() {
        if (getWidth() == 0 || getHeight() == 0) return;

        Bitmap bitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
        Canvas tempCanvas = new Canvas(bitmap);
        super.draw(tempCanvas);

        RenderScript rs = RenderScript.create(getContext());
        Allocation input = Allocation.createFromBitmap(rs, bitmap);
        Allocation output = Allocation.createTyped(rs, input.getType());
        ScriptIntrinsicBlur blurScript = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs));
        blurScript.setRadius(blurRadius);
        blurScript.setInput(input);
        blurScript.forEach(output);
        output.copyTo(bitmap);

        setBackground(new BitmapDrawable(getResources(), bitmap));
        rs.destroy();
        input.destroy();
        output.destroy();
    }

    private void updateBlur() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
            applyRenderEffect();
        } else {
            applyRenderScriptBlur();
        }
    }
}

接着创建React Native桥接管理器:

// BlurViewManager.java
package com.your.app.package;

import com.facebook.react.uimanager.SimpleViewManager;
import com.facebook.react.uimanager.ThemedReactContext;
import com.facebook.react.uimanager.annotations.ReactProp;

public class BlurViewManager extends SimpleViewManager<BlurView> {
    public static final String REACT_CLASS = "CustomBlurView";

    @Override
    public String getName() {
        return REACT_CLASS;
    }

    @Override
    protected BlurView createViewInstance(ThemedReactContext reactContext) {
        return new BlurView(reactContext);
    }

    @ReactProp(name = "blurRadius")
    public void setBlurRadius(BlurView view, int radius) {
        view.setBlurRadius(radius);
    }
}

在MainApplication.java中注册该模块:

@Override
protected List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
    return Arrays.asList(
            new BlurViewManager(),
            // 其他已注册的ViewManager
    );
}

2. JS层跨平台封装

封装统一组件,iOS直接使用@react-native-community/blur的BlurView,Android使用自定义原生组件:

// CustomBlurView.jsx
import React from 'react';
import { Platform, requireNativeComponent } from 'react-native';
import { BlurView as RNCommunityBlur } from '@react-native-community/blur';

const NativeBlurView = requireNativeComponent('CustomBlurView');

const CustomBlurView = ({ blurRadius, blurType = 'light', style, children, ...props }) => {
  if (Platform.OS === 'ios') {
    return (
      <RNCommunityBlur
        style={style}
        blurType={blurType}
        blurAmount={blurRadius}
        {...props}
      >
        {children}
      </RNCommunityBlur>
    );
  }

  return (
    <NativeBlurView
      style={style}
      blurRadius={blurRadius}
      {...props}
    >
      {children}
    </NativeBlurView>
  );
};

export default CustomBlurView;

3. 使用示例

// 示例组件
import React from 'react';
import { View, Text, StyleSheet } from 'react-native';
import CustomBlurView from './CustomBlurView';

export default function App() {
  return (
    <View style={styles.container}>
      <Text style={styles.bgText}>这是底层的测试文本</Text>
      <CustomBlurView
        style={styles.blurContainer}
        blurRadius={12}
      >
        <Text style={styles.fgText}>模糊层上的内容</Text>
      </CustomBlurView>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  bgText: {
    fontSize: 28,
    color: '#ff4444',
    position: 'absolute',
  },
  blurContainer: {
    width: 250,
    height: 120,
    justifyContent: 'center',
    alignItems: 'center',
    borderRadius: 12,
    padding: 16,
  },
  fgText: {
    fontSize: 20,
    color: '#ffffff',
    fontWeight: '600',
  },
});

核心优势

  • Android端支持wrap_content、match_parent及约束布局,彻底解决原包强制全屏的问题
  • iOS复用成熟的社区组件,保证稳定性和原生体验
  • 支持动态调整模糊半径,适配不同场景需求

内容的提问来源于stack exchange,提问作者ibrar hussain

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 19:07:03