
前端移动开发UI组件跨平台【免费下载链接】react-native-bottom-sheetA performant interactive bottom sheet with fully configurable options 项目地址https://gitcode.com/gh_mirrors/re/react-native-bottom-sheet点击查看免费下载底部页脚Footer是 BottomSheet 中常见的高价值交互区域它通常承载操作按钮如展开 / 收起、快捷入口或表单提交区需要始终吸附在面板底部边缘并随面板拖拽、键盘弹出而正确位移。本文以react-native-bottom-sheetv4 版本文档提供的预置组件BottomSheetFooter为核心完整讲解它的三个 Props、与footerComponent的接入方式并结合仓库源码剖析其位置计算与键盘适配原理最终带你实现一个带安全区适配、随面板索引旋转箭头动画的自定义页脚。一、BottomSheetFooter 是什么BottomSheetFooter是仓库提供的预置页脚组件它负责把任意自定义内容钉在 BottomSheet 的底部并自动响应键盘的弹出与收起。官方文档对其定位是A pre-built component that sticks to the bottom of the BottomSheet and can be modify to fit your own custom interaction.即它自身不提供业务 UI只负责定位与动画行为——你传入的children是什么页脚就渲染什么。这让它既能用于简单文本页脚也能承载可点击按钮、搜索框等复杂交互。在 v4 文档中该组件对应两个使用层级作为BottomSheet的footerComponent直接传入接收由面板内部计算好的animatedFooterPosition作为自定义页脚组件的内部包装层用于承接定位逻辑详见第三节。二、组件 Props 详解根据 bottomsheetfooter.md 的官方定义BottomSheetFooter提供以下 Props1. animatedFooterPosition计算后的页脚动画位置SharedValue。这是面板内部通过派生值useDerivedValue实时算出的位移量页面拖拽、键盘变化时它都会同步更新。该值由BottomSheetFooterContainer计算后通过footerComponent传入BottomSheetFooter拿到后直接驱动自身的translateY动画。typedefaultrequiredAnimated.SharedValuenumber0NO2. bottomInset页脚下方需要追加的底部留白。典型用法是传入react-native-safe-area-context的useSafeAreaInsets()返回的bottom值用来避开 Home Indicator / 底部刘海。类型为number默认值0。typedefaultrequirednumber0NO3. children要放置在页脚中的组件。可以是单个ReactNode或数组。注意源码实现中当children null时整个页脚不渲染见 BottomSheetFooter.tsx。typedefaultrequiredReactNode | ReactNode[]undefinedNO此外在类型定义 types.d.ts 中还可以看到第四个可选 Propstyle?: ViewStyle用于给页脚容器追加自定义样式它与内置容器样式按[styles.container, style, containerAnimatedStyle]的顺序合并。三、基础用法把页脚挂到 BottomSheet 上使用BottomSheetFooter的标准姿势是把它作为BottomSheet的footerComponent渲染。以下完整示例来自官方文档import React, { useCallback, useMemo, useRef } from react; import { View, Text, StyleSheet } from react-native; import BottomSheet, { BottomSheetFooter } from gorhom/bottom-sheet; const App () { // ref const bottomSheetRef useRefBottomSheet(null); // variables const snapPoints useMemo(() [25%, 50%], []); // renders const renderFooter useCallback( props ( BottomSheetFooter {...props} bottomInset{24} View style{styles.footerContainer} Text style{styles.footerText}Footer/Text /View /BottomSheetFooter ), [] ); return ( View style{styles.container} BottomSheet ref{bottomSheetRef} index{1} snapPoints{snapPoints} footerComponent{renderFooter} View style{styles.contentContainer} TextAwesome /Text /View /BottomSheet /View ); }; const styles StyleSheet.create({ container: { flex: 1, padding: 24, backgroundColor: grey, }, contentContainer: { flex: 1, alignItems: center, }, footerContainer: { padding: 12, margin: 12, borderRadius: 12, backgroundColor: #80f, }, footerText: { textAlign: center, color: white, fontWeight: 800, }, }); export default App;几个值得注意的细节renderFooter接收的props里就包含animatedFooterPosition所以用展开运算符{...props}透传给BottomSheetFooter即可无需手动构造bottomInset{24}会在页脚下方额外留出 24 像素使页脚与面板底部边缘保持间距footerComponent的类型签名是React.FCBottomSheetFooterProps见 bottomSheet/types.d.ts。四、自定义交互页脚继承 Props 并驱动动画官方在 custom-footer.mdx 中给出了自定义页脚的标准范式自定义组件的 Props 接口继承BottomSheetFooterProps从而把animatedFooterPosition暴露进自己的接口渲染时用BottomSheetFooter包裹业务内容业务动画如箭头旋转、透明度则通过useBottomSheet()拿到的animatedIndex来驱动。仓库示例 CustomFooter.tsx 是这一模式的完整落地一个悬浮在右下角的圆形按钮面板从0号快照点到1号快照点时箭头图标旋转 180 度按钮透明度随索引从 0 渐变到 1点击后根据当前animatedIndex调用expand()或collapse()切换面板import React, { memo, useCallback, useMemo } from react; import { Pressable, StyleSheet } from react-native; import { BottomSheetFooter, BottomSheetFooterProps, useBottomSheet, } from gorhom/bottom-sheet; import { useSafeAreaInsets } from react-native-safe-area-context; import Animated, { Extrapolation, interpolate, useAnimatedStyle, } from react-native-reanimated; import { toRad } from react-native-redash; const AnimatedRectButton Animated.createAnimatedComponent(Pressable); interface CustomFooterProps extends BottomSheetFooterProps {} const CustomFooterComponent ({ animatedFooterPosition, }: CustomFooterProps) { const { bottom: bottomSafeArea } useSafeAreaInsets(); const { expand, collapse, animatedIndex } useBottomSheet(); const arrowAnimatedStyle useAnimatedStyle(() { const arrowRotate interpolate( animatedIndex.value, [0, 1], [toRad(0), toRad(-180)], Extrapolation.CLAMP ); return { transform: [{ rotate: ${arrowRotate}rad }] }; }, [animatedIndex.value]); const containerAnimatedStyle useAnimatedStyle( () ({ opacity: interpolate( animatedIndex.value, [-0.85, 0], [0, 1], Extrapolation.CLAMP ), }), [animatedIndex] ); const handleArrowPress useCallback(() { if (animatedIndex.value 0) { expand(); } else { collapse(); } }, [expand, collapse, animatedIndex]); return ( BottomSheetFooter bottomInset{bottomSafeArea} animatedFooterPosition{animatedFooterPosition} AnimatedRectButton style{containerStyle} onPress{handleArrowPress} Animated.Text style{arrowStyle}⌃/Animated.Text /AnimatedRectButton /BottomSheetFooter ); }; export const CustomFooter memo(CustomFooterComponent);配套的接入方式与文档一致footerComponent{CustomFooter}直接传入组件引用即可。真实运行的接入示例见 FooterExample.tsx它还演示了与keyboardBehaviorinteractive、keyboardBlurBehaviorrestore、enablePanDownToClose等 Props 的组合使用。五、源码剖析页脚位置是如何算出来的5.1 位置计算BottomSheetFooterContainer当你传入footerComponent时BottomSheet会在内容之后渲染BottomSheetFooterContainer见 BottomSheet.tsx。这个容器本身不渲染任何 UI唯一职责是计算animatedFooterPosition并传给你的页脚组件计算逻辑在 BottomSheetFooterContainer.tsxconst animatedFooterPosition useDerivedValue(() { const keyboardHeight animatedKeyboardHeightInContainer.value; let footerTranslateY Math.max( 0, animatedContainerHeight.value - animatedPosition.value ); if (animatedKeyboardState.value KEYBOARD_STATE.SHOWN) { footerTranslateY footerTranslateY - keyboardHeight; } footerTranslateY footerTranslateY - animatedFooterHeight.value - animatedHandleHeight.value; return footerTranslateY; }, [...]);可以看到页脚最终位移量 面板容器高度 - 面板当前位置 - 键盘高度若键盘可见- 页脚自身高度 - 手柄高度并且用Math.max(0, ...)保证不会把页脚顶出屏幕之外。5.2 键盘适配BottomSheetFooter 的渲染逻辑BottomSheetFooter本体BottomSheetFooter.tsx则负责把该位置应用到动画视图上并处理bottomInset与键盘的关系const containerAnimatedStyle useAnimatedStyle(() { let footerTranslateY animatedFooterPosition.value; /** * Offset the bottom inset only when keyboard is not shown */ if (animatedKeyboardState.value ! KEYBOARD_STATE.SHOWN) { footerTranslateY footerTranslateY - bottomInset; } return { transform: [ { translateY: Math.max(0, footerTranslateY), }, ], }; }, [bottomInset, animatedKeyboardState, animatedFooterPosition]);关键行为键盘弹出时bottomInset不再生效避免页脚被键盘顶起后与安全区留白叠加造成额外偏移。这正是自动响应键盘的核心实现。同时组件通过onLayout回调把自身高度写回animatedFooterHeight第 46-55 行反馈给上一节的位移计算形成闭环。5.3 容器样式绝对定位与层级styles.ts 定义了页脚容器的默认样式export const styles StyleSheet.create({ container: { position: absolute, top: 0, left: 0, right: 0, zIndex: 9999, pointerEvents: box-none, }, });position: absolute 左右撑满使页脚脱离文档流、覆盖在面板内容之上zIndex: 9999保证页脚始终处于面板内容最上层pointerEvents: box-none使容器自身不拦截触摸点击可穿透到页脚子组件。5.4 滚动内容避让enableFooterMarginAdjustment页脚会覆盖面板内容的底部区域。为避免滚动列表的最后一项被页脚遮挡滚动类组件BottomSheetScrollView、BottomSheetFlatList、BottomSheetSectionList、BottomSheetVirtualizedList、BottomSheetFlashList以及BottomSheetView都支持enableFooterMarginAdjustment属性默认false。开启后滚动容器会依据animatedFooterHeight.value动态追加marginBottom把内容底部撑高一个页脚的高度。实现见 createBottomSheetScrollableComponent.tsx 与 BottomSheetView.tsx。六、接入 Checklist 与关联资料自定义页脚组件继承BottomSheetFooterProps以获得animatedFooterPosition渲染时用BottomSheetFooter包装并透传animatedFooterPosition用useSafeAreaInsets()的bottom作为bottomInset避免底部安全区遮挡交互类动画旋转、透明度、缩放通过useBottomSheet()的animatedIndex驱动若页脚固定显示且内容可滚动记得给滚动组件开启enableFooterMarginAdjustment。更多关联资料组件 Props 官方文档bottomsheetfooter.md自定义页脚完整指南custom-footer.mdx页脚组件实现BottomSheetFooter.tsx页脚位置计算容器BottomSheetFooterContainer.tsx页脚类型定义types.d.ts可运行示例FooterExample.tsx 与 CustomFooter.tsx赞分享前端移动开发UI组件跨平台【免费下载链接】react-native-bottom-sheetA performant interactive bottom sheet with fully configurable options 项目地址https://gitcode.com/gh_mirrors/re/react-native-bottom-sheet点击查看免费下载相关推荐React Native Bottom Sheet 自定义底部组件完全指南React Native Bottom Sheet 自定义底部组件完全指南 前言 在移动应用开发中底部弹窗 Bottom Sheet 是一种常见的交互组件。g前端移动开发UI组件跨平台react-native-bottom-sheet 的 BottomSheetFooter 组件详解吸底 Footer 的定位、动画与自定义实践react native bottom sheet 的 BottomSheetFooter 组件详解吸底 Footer 的定位、动画与自定义实践 导读 Bot前端移动开发UI组件跨平台react-native-bottom-sheet 组件 Props 全解从吸附点、手势到键盘与动画的完整配置指南react native bottom sheet 组件 Props 全解从吸附点、手势到键盘与动画的完整配置指南 本篇指南以 react native bo前端移动开发UI组件跨平台上一篇BannerViewPager 终极指南10 分钟搞定 Android 轮播图配置下一篇3分钟掌握Element Table横向滚动条优化技巧创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考