如何在Expo版React Native中创建带曲线的视图?
解决方案
一、带内阴影的曲线View
方法1:使用react-native-svg实现精确效果
先安装依赖:
npm install react-native-svg # 或 yarn add react-native-svg
通过SVG路径绘制曲线,配合滤镜实现内阴影:
import React from 'react'; import { View } from 'react-native'; import Svg, { Path, Defs, Filter, FeFlood, FeComposite, FeGaussianBlur } from 'react-native-svg'; const CurvedInsetShadowView = ({ width = 300, height = 200, curveRadius = 40 }) => { return ( <View style={{ width, height, position: 'relative' }}> <Svg width="100%" height="100%" viewBox={`0 0 ${width} ${height}`}> <Defs> {/* 内阴影滤镜 */} <Filter id="insetShadow"> <FeFlood floodColor="#000" floodOpacity={0.2} /> <FeComposite operator="in" in2="SourceGraphic" /> <FeGaussianBlur stdDeviation={4} /> <FeComposite operator="over" in="SourceGraphic" /> </Filter> </Defs> {/* 顶部上凸曲线路径 */} <Path d={`M 0 ${height} L 0 ${curveRadius} Q ${width/2} ${-curveRadius/2} ${width} ${curveRadius} L ${width} ${height} Z`} fill="#fff" filter="url(#insetShadow)" stroke="transparent" /> </Svg> {/* 内容容器 */} <View style={{ position: 'absolute', inset: 0, padding: 16, }}> {/* 此处添加你的内容 */} </View> </View> ); }; export default CurvedInsetShadowView;
可调整参数:
curveRadius:控制曲线弧度stdDeviation:阴影模糊程度floodOpacity:阴影透明度
方法2:纯View叠加(无额外依赖)
通过多层View模拟曲线和内阴影效果:
import React from 'react'; import { View, StyleSheet } from 'react-native'; const CurvedInsetShadowView = ({ width = 300, height = 200, curveRadius = 40 }) => { return ( <View style={[styles.container, { width, height }]}> {/* 底层阴影层 */} <View style={[styles.shadowLayer, { borderTopLeftRadius: curveRadius, borderTopRightRadius: curveRadius, height: height - curveRadius/2, top: curveRadius/2, }]} /> {/* 上层白色容器 */} <View style={[styles.contentContainer, { borderTopLeftRadius: curveRadius, borderTopRightRadius: curveRadius, }]}> {/* 顶部曲线遮罩 */} <View style={[styles.curveMask, { width: curveRadius * 2, height: curveRadius, borderRadius: curveRadius, top: -curveRadius/2, alignSelf: 'center', }]} /> {/* 内容区域 */} <View style={styles.innerContent}> {/* 此处添加你的内容 */} </View> </View> </View> ); }; const styles = StyleSheet.create({ container: { position: 'relative', overflow: 'hidden', }, shadowLayer: { position: 'absolute', left: 0, right: 0, backgroundColor: 'transparent', shadowColor: '#000', shadowOffset: { width: 0, height: 2 }, shadowOpacity: 0.2, shadowRadius: 4, elevation: 3, // Android阴影 }, contentContainer: { flex: 1, backgroundColor: '#fff', position: 'relative', }, curveMask: { backgroundColor: '#fff', shadowColor: '#000', shadowOffset: { width: 0, height: -2 }, shadowOpacity: 0.2, shadowRadius: 4, elevation: 3, }, innerContent: { flex: 1, padding: 16, }, }); export default CurvedInsetShadowView;
二、自定义底部导航栏
用SVG绘制顶部内凹曲线,配合偏移的中间按钮实现效果:
import React from 'react'; import { View, TouchableOpacity, Text, StyleSheet } from 'react-native'; import Svg, { Path } from 'react-native-svg'; const CustomBottomNav = ({ navigation, currentRoute }) => { const navItems = [ { label: '首页', route: 'Home' }, { label: '中间', route: 'Middle' }, { label: '我的', route: 'Profile' }, ]; return ( <View style={styles.navContainer}> {/* SVG绘制顶部内凹曲线 */} <Svg width="100%" height={40} viewBox="0 0 375 40"> <Path d={`M 0 40 L 0 0 Q 187.5 20 375 0 L 375 40 Z`} fill="#fff" stroke="transparent" /> </Svg> {/* 导航按钮容器 */} <View style={styles.navButtonsContainer}> {navItems.map((item, index) => ( <TouchableOpacity key={item.route} style={[ styles.navButton, index === 1 ? styles.middleButton : null, currentRoute === item.route ? styles.activeButton : null, ]} onPress={() => navigation.navigate(item.route)} > <Text style={currentRoute === item.route ? styles.activeText : styles.text}> {item.label} </Text> </TouchableOpacity> ))} </View> </View> ); }; const styles = StyleSheet.create({ navContainer: { position: 'absolute', bottom: 0, left: 0, right: 0, backgroundColor: '#fff', shadowColor: '#000', shadowOffset: { width: 0, height: -2 }, shadowOpacity: 0.1, shadowRadius: 4, elevation: 5, }, navButtonsContainer: { flexDirection: 'row', justifyContent: 'space-around', alignItems: 'center', paddingBottom: 16, paddingTop: 8, }, navButton: { flex: 1, alignItems: 'center', paddingVertical: 8, }, middleButton: { marginTop: -20, // 适配曲线位置,向上偏移 backgroundColor: '#007AFF', borderRadius: 30, paddingHorizontal: 20, }, text: { color: '#666', fontSize: 12, }, activeText: { color: '#fff', fontSize: 12, }, }); export default CustomBottomNav;
关键提示
react-native-inset-shadow对曲线View的内阴影支持有限,SVG或叠加View的方法更灵活- Android阴影用
elevation,iOS用shadow系列属性,需兼顾双平台 - 调整SVG路径的
Q参数可修改曲线弧度,按需适配设计稿
内容的提问来源于stack exchange,提问作者Admonster Ad
相关产品推荐
相关产品推荐

