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

如何在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 18:00:35