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
相关产品推荐
相关产品推荐

