14de3fbc9S猫头猫/** 24de3fbc9S猫头猫 * 支持长按拖拽排序的flatlist,右边加个固定的按钮,拖拽排序。 34de3fbc9S猫头猫 * 考虑到方便实现+节省性能,整个app内的拖拽排序都遵守以下实现。 44de3fbc9S猫头猫 * 点击会出现 54de3fbc9S猫头猫 */ 64de3fbc9S猫头猫 73b155a65S猫头猫import globalStyle from '@/constants/globalStyle'; 84de3fbc9S猫头猫import {iconSizeConst} from '@/constants/uiConst'; 94de3fbc9S猫头猫import useTextColor from '@/hooks/useTextColor'; 104de3fbc9S猫头猫import rpx from '@/utils/rpx'; 116cb76c0cS猫头猫import {FlashList} from '@shopify/flash-list'; 124de3fbc9S猫头猫import React, { 134de3fbc9S猫头猫 ForwardedRef, 144de3fbc9S猫头猫 forwardRef, 154de3fbc9S猫头猫 memo, 164de3fbc9S猫头猫 useEffect, 17ef40425aS猫头猫 useMemo, 184de3fbc9S猫头猫 useRef, 194de3fbc9S猫头猫 useState, 204de3fbc9S猫头猫} from 'react'; 21ccf779d0S猫头猫import {LayoutRectangle, Pressable, StyleSheet, View} from 'react-native'; 22bec1e603S猫头猫import { 23bec1e603S猫头猫 runOnJS, 24bec1e603S猫头猫 useDerivedValue, 25bec1e603S猫头猫 useSharedValue, 26bec1e603S猫头猫} from 'react-native-reanimated'; 27*5589cdf3S猫头猫import Icon from '@/components/base/icon.tsx'; 284de3fbc9S猫头猫 294de3fbc9S猫头猫const defaultZIndex = 10; 304de3fbc9S猫头猫 314de3fbc9S猫头猫interface ISortableFlatListProps<T> { 324de3fbc9S猫头猫 data: T[]; 334de3fbc9S猫头猫 renderItem: (props: {item: T; index: number}) => JSX.Element; 344de3fbc9S猫头猫 // 高度 354de3fbc9S猫头猫 itemHeight: number; 3634588741S猫头猫 itemJustifyContent?: 3734588741S猫头猫 | 'flex-start' 3834588741S猫头猫 | 'flex-end' 3934588741S猫头猫 | 'center' 4034588741S猫头猫 | 'space-between' 4134588741S猫头猫 | 'space-around' 4234588741S猫头猫 | 'space-evenly'; 434de3fbc9S猫头猫 // 滚动list距离顶部的距离, 这里写的不好 444de3fbc9S猫头猫 marginTop: number; 454de3fbc9S猫头猫 /** 拖拽时的背景色 */ 464de3fbc9S猫头猫 activeBackgroundColor?: string; 474de3fbc9S猫头猫 /** 交换结束 */ 484de3fbc9S猫头猫 onSortEnd?: (newData: T[]) => void; 494de3fbc9S猫头猫} 504de3fbc9S猫头猫 514de3fbc9S猫头猫export default function SortableFlatList<T extends any = any>( 524de3fbc9S猫头猫 props: ISortableFlatListProps<T>, 534de3fbc9S猫头猫) { 544de3fbc9S猫头猫 const { 554de3fbc9S猫头猫 data, 564de3fbc9S猫头猫 renderItem, 574de3fbc9S猫头猫 itemHeight, 5834588741S猫头猫 itemJustifyContent, 594de3fbc9S猫头猫 marginTop, 604de3fbc9S猫头猫 activeBackgroundColor, 614de3fbc9S猫头猫 onSortEnd, 624de3fbc9S猫头猫 } = props; 634de3fbc9S猫头猫 644de3fbc9S猫头猫 // 不要干扰原始数据 654de3fbc9S猫头猫 const [_data, _setData] = useState([...(data ?? [])]); 664de3fbc9S猫头猫 // 是否禁止滚动 674de3fbc9S猫头猫 const [scrollEnabled, setScrollEnabled] = useState(true); 684de3fbc9S猫头猫 // 是否处在激活状态, -1表示无,其他表示当前激活的下标 694de3fbc9S猫头猫 const activeRef = useRef(-1); 704de3fbc9S猫头猫 const [activeItem, setActiveItem] = useState<T | null>(null); 714de3fbc9S猫头猫 724de3fbc9S猫头猫 const layoutRef = useRef<LayoutRectangle>(); 734de3fbc9S猫头猫 // listref 746cb76c0cS猫头猫 const listRef = useRef<FlashList<T> | null>(null); 754de3fbc9S猫头猫 // fakeref 764de3fbc9S猫头猫 const fakeItemRef = useRef<View | null>(null); 774de3fbc9S猫头猫 // contentoffset 789cc05961S猫头猫 const contentOffsetYRef = useRef<number>(-1); 79ef40425aS猫头猫 const targetOffsetYRef = useRef<number>(0); 80ef40425aS猫头猫 81ef40425aS猫头猫 const direction = useSharedValue(0); 824de3fbc9S猫头猫 834de3fbc9S猫头猫 useEffect(() => { 844de3fbc9S猫头猫 _setData([...(data ?? [])]); 854de3fbc9S猫头猫 }, [data]); 864de3fbc9S猫头猫 874de3fbc9S猫头猫 const initDragPageY = useRef<number>(0); 884de3fbc9S猫头猫 const initDragLocationY = useRef<number>(0); 894de3fbc9S猫头猫 const offsetRef = useRef<number>(0); 904de3fbc9S猫头猫 914de3fbc9S猫头猫 //#region 滚动 92ef40425aS猫头猫 const scrollingRef = useRef(false); 934de3fbc9S猫头猫 94ef40425aS猫头猫 // 列表整体的高度 954ddc4470S猫头猫 const listContentHeight = useMemo( 964ddc4470S猫头猫 () => itemHeight * data.length, 974ddc4470S猫头猫 [data, itemHeight], 984ddc4470S猫头猫 ); 99ef40425aS猫头猫 100ef40425aS猫头猫 function scrollToTarget(forceScroll = false) { 101ef40425aS猫头猫 // 未选中 102ef40425aS猫头猫 if (activeRef.current === -1) { 103ef40425aS猫头猫 scrollingRef.current = false; 1044de3fbc9S猫头猫 return; 1054de3fbc9S猫头猫 } 106ef40425aS猫头猫 107ef40425aS猫头猫 // 滚动中就不滚了 / 108ef40425aS猫头猫 if (scrollingRef.current && !forceScroll) { 109ef40425aS猫头猫 scrollingRef.current = true; 110ef40425aS猫头猫 return; 1114de3fbc9S猫头猫 } 112ef40425aS猫头猫 // 方向是0 113ef40425aS猫头猫 if (direction.value === 0) { 114ef40425aS猫头猫 scrollingRef.current = false; 115ef40425aS猫头猫 return; 116ef40425aS猫头猫 } 117ef40425aS猫头猫 118ef40425aS猫头猫 const nextTarget = 119ef40425aS猫头猫 Math.sign(direction.value) * 120ef40425aS猫头猫 Math.max(Math.abs(direction.value), 0.3) * 121ef40425aS猫头猫 300 + 122ef40425aS猫头猫 contentOffsetYRef.current; 123ef40425aS猫头猫 // 当前到极限了 1244de3fbc9S猫头猫 if ( 125ef40425aS猫头猫 (contentOffsetYRef.current <= 2 && 126ef40425aS猫头猫 nextTarget < contentOffsetYRef.current) || 127ef40425aS猫头猫 (contentOffsetYRef.current >= 12815a52c01S猫头猫 listContentHeight - (layoutRef.current?.height ?? 0) - 2 && 129ef40425aS猫头猫 nextTarget > contentOffsetYRef.current) 1304de3fbc9S猫头猫 ) { 131ef40425aS猫头猫 scrollingRef.current = false; 132ef40425aS猫头猫 return; 1334de3fbc9S猫头猫 } 134ef40425aS猫头猫 scrollingRef.current = true; 135ef40425aS猫头猫 // 超出区域 136ef40425aS猫头猫 targetOffsetYRef.current = Math.min( 137ef40425aS猫头猫 Math.max(0, nextTarget), 13815a52c01S猫头猫 listContentHeight - (layoutRef.current?.height ?? 0), 139ef40425aS猫头猫 ); 140ef40425aS猫头猫 listRef.current?.scrollToOffset({ 141ef40425aS猫头猫 animated: true, 142ef40425aS猫头猫 offset: targetOffsetYRef.current, 143ef40425aS猫头猫 }); 1444de3fbc9S猫头猫 } 1454de3fbc9S猫头猫 146ef40425aS猫头猫 useDerivedValue(() => { 147ef40425aS猫头猫 // 正在滚动 148ef40425aS猫头猫 if (scrollingRef.current) { 149ef40425aS猫头猫 return; 150ef40425aS猫头猫 } else if (direction.value !== 0) { 151ef40425aS猫头猫 // 开始滚动 152bec1e603S猫头猫 runOnJS(scrollToTarget)(); 153ef40425aS猫头猫 } 1544de3fbc9S猫头猫 }, []); 1554de3fbc9S猫头猫 1564de3fbc9S猫头猫 //#endregion 1574de3fbc9S猫头猫 1584de3fbc9S猫头猫 return ( 1593b155a65S猫头猫 <View style={globalStyle.fwflex1}> 1604de3fbc9S猫头猫 {/* 纯展示 */} 1614de3fbc9S猫头猫 <FakeFlatListItem 1624de3fbc9S猫头猫 ref={_ => (fakeItemRef.current = _)} 1634de3fbc9S猫头猫 backgroundColor={activeBackgroundColor} 1644de3fbc9S猫头猫 renderItem={renderItem} 1654de3fbc9S猫头猫 itemHeight={itemHeight} 1664de3fbc9S猫头猫 item={activeItem} 16734588741S猫头猫 itemJustifyContent={itemJustifyContent} 1684de3fbc9S猫头猫 /> 1696cb76c0cS猫头猫 <FlashList 1704de3fbc9S猫头猫 scrollEnabled={scrollEnabled} 1714de3fbc9S猫头猫 ref={_ => { 1724de3fbc9S猫头猫 listRef.current = _; 1734de3fbc9S猫头猫 }} 1744de3fbc9S猫头猫 onLayout={evt => { 1754de3fbc9S猫头猫 layoutRef.current = evt.nativeEvent.layout; 1764de3fbc9S猫头猫 }} 1774de3fbc9S猫头猫 data={_data} 1786cb76c0cS猫头猫 estimatedItemSize={itemHeight} 179ef40425aS猫头猫 scrollEventThrottle={16} 1804de3fbc9S猫头猫 onTouchStart={e => { 1814de3fbc9S猫头猫 if (activeRef.current !== -1) { 1824de3fbc9S猫头猫 // 相对于整个页面顶部的距离 1834de3fbc9S猫头猫 initDragPageY.current = e.nativeEvent.pageY; 1844de3fbc9S猫头猫 initDragLocationY.current = e.nativeEvent.locationY; 1854de3fbc9S猫头猫 } 1864de3fbc9S猫头猫 }} 1874de3fbc9S猫头猫 onTouchMove={e => { 1884de3fbc9S猫头猫 if (activeRef.current !== -1) { 1894de3fbc9S猫头猫 offsetRef.current = 1904de3fbc9S猫头猫 e.nativeEvent.pageY - 1914de3fbc9S猫头猫 (marginTop ?? layoutRef.current?.y ?? 0) - 1924de3fbc9S猫头猫 itemHeight / 2; 1934de3fbc9S猫头猫 1944de3fbc9S猫头猫 if (offsetRef.current < 0) { 1954de3fbc9S猫头猫 offsetRef.current = 0; 1964de3fbc9S猫头猫 } else if ( 1974de3fbc9S猫头猫 offsetRef.current > 1984de3fbc9S猫头猫 (layoutRef.current?.height ?? 0) - itemHeight 1994de3fbc9S猫头猫 ) { 2004de3fbc9S猫头猫 offsetRef.current = 2014de3fbc9S猫头猫 (layoutRef.current?.height ?? 0) - itemHeight; 2024de3fbc9S猫头猫 } 2034de3fbc9S猫头猫 fakeItemRef.current!.setNativeProps({ 2044de3fbc9S猫头猫 top: offsetRef.current, 2054de3fbc9S猫头猫 opacity: 1, 2064de3fbc9S猫头猫 zIndex: 100, 2074de3fbc9S猫头猫 }); 2084de3fbc9S猫头猫 2094de3fbc9S猫头猫 // 如果超出范围,停止 2104de3fbc9S猫头猫 if (offsetRef.current < itemHeight * 2) { 2114de3fbc9S猫头猫 // 上滑 212ef40425aS猫头猫 direction.value = 213ef40425aS猫头猫 offsetRef.current / itemHeight / 2 - 1; 2144de3fbc9S猫头猫 } else if ( 2154de3fbc9S猫头猫 offsetRef.current > 2164de3fbc9S猫头猫 (layoutRef.current?.height ?? 0) - 3 * itemHeight 2174de3fbc9S猫头猫 ) { 2184de3fbc9S猫头猫 // 下滑 219ef40425aS猫头猫 direction.value = 220ef40425aS猫头猫 (offsetRef.current - 221ef40425aS猫头猫 (layoutRef.current?.height ?? 0) + 222ef40425aS猫头猫 3 * itemHeight) / 223ef40425aS猫头猫 itemHeight / 224ef40425aS猫头猫 2; 2254de3fbc9S猫头猫 } else { 226ef40425aS猫头猫 // 不滑动 227ef40425aS猫头猫 direction.value = 0; 2284de3fbc9S猫头猫 } 2294de3fbc9S猫头猫 } 2304de3fbc9S猫头猫 }} 2314de3fbc9S猫头猫 onTouchEnd={e => { 2324de3fbc9S猫头猫 if (activeRef.current !== -1) { 2334de3fbc9S猫头猫 // 计算最终的位置,触发onSortEnd 2344de3fbc9S猫头猫 let index = activeRef.current; 2359cc05961S猫头猫 if (contentOffsetYRef.current !== -1) { 2364de3fbc9S猫头猫 index = Math.round( 2374de3fbc9S猫头猫 (contentOffsetYRef.current + 2384de3fbc9S猫头猫 offsetRef.current) / 2394de3fbc9S猫头猫 itemHeight, 2404de3fbc9S猫头猫 ); 2414de3fbc9S猫头猫 } else { 2424de3fbc9S猫头猫 // 拖动的距离 2434de3fbc9S猫头猫 index = 2444de3fbc9S猫头猫 activeRef.current + 2454de3fbc9S猫头猫 Math.round( 2464de3fbc9S猫头猫 (e.nativeEvent.pageY - 2474de3fbc9S猫头猫 initDragPageY.current + 2484de3fbc9S猫头猫 initDragLocationY.current) / 2494de3fbc9S猫头猫 itemHeight, 2504de3fbc9S猫头猫 ); 2514de3fbc9S猫头猫 } 2524de3fbc9S猫头猫 index = Math.min(data.length, Math.max(index, 0)); 2534de3fbc9S猫头猫 // from: activeRef.current to: index 2544de3fbc9S猫头猫 if (activeRef.current !== index) { 2554de3fbc9S猫头猫 let nData = _data 2564de3fbc9S猫头猫 .slice(0, activeRef.current) 2574de3fbc9S猫头猫 .concat(_data.slice(activeRef.current + 1)); 2584de3fbc9S猫头猫 nData.splice(index, 0, activeItem as T); 2594de3fbc9S猫头猫 onSortEnd?.(nData); 2604de3fbc9S猫头猫 // 测试用,正式时移除掉 2614de3fbc9S猫头猫 // _setData(nData); 2624de3fbc9S猫头猫 } 2634de3fbc9S猫头猫 } 264ef40425aS猫头猫 scrollingRef.current = false; 2654de3fbc9S猫头猫 activeRef.current = -1; 2664de3fbc9S猫头猫 setScrollEnabled(true); 2674de3fbc9S猫头猫 setActiveItem(null); 2684de3fbc9S猫头猫 fakeItemRef.current!.setNativeProps({ 2694de3fbc9S猫头猫 top: 0, 2704de3fbc9S猫头猫 opacity: 0, 2714de3fbc9S猫头猫 zIndex: -1, 2724de3fbc9S猫头猫 }); 2734de3fbc9S猫头猫 }} 2744de3fbc9S猫头猫 onTouchCancel={() => { 27599b6e7ceS猫头猫 // todo: 滑动很快的时候会触发取消,native的flatlist就这样 27676cce596S猫头猫 activeRef.current = -1; 277ef40425aS猫头猫 scrollingRef.current = false; 27876cce596S猫头猫 setScrollEnabled(true); 27976cce596S猫头猫 setActiveItem(null); 28076cce596S猫头猫 fakeItemRef.current!.setNativeProps({ 28176cce596S猫头猫 top: 0, 28276cce596S猫头猫 opacity: 0, 28376cce596S猫头猫 zIndex: -1, 28476cce596S猫头猫 }); 2859cc05961S猫头猫 contentOffsetYRef.current = -1; 2864de3fbc9S猫头猫 }} 2874de3fbc9S猫头猫 onScroll={e => { 2884de3fbc9S猫头猫 contentOffsetYRef.current = e.nativeEvent.contentOffset.y; 289ef40425aS猫头猫 if ( 290ef40425aS猫头猫 activeRef.current !== -1 && 291ef40425aS猫头猫 Math.abs( 292ef40425aS猫头猫 contentOffsetYRef.current - 293ef40425aS猫头猫 targetOffsetYRef.current, 294ef40425aS猫头猫 ) < 2 295ef40425aS猫头猫 ) { 296ef40425aS猫头猫 scrollToTarget(true); 297ef40425aS猫头猫 } 2984de3fbc9S猫头猫 }} 2994de3fbc9S猫头猫 renderItem={({item, index}) => { 3004de3fbc9S猫头猫 return ( 3014de3fbc9S猫头猫 <SortableFlatListItem 3024de3fbc9S猫头猫 setScrollEnabled={setScrollEnabled} 3034de3fbc9S猫头猫 activeRef={activeRef} 3044de3fbc9S猫头猫 renderItem={renderItem} 3054de3fbc9S猫头猫 item={item} 3064de3fbc9S猫头猫 index={index} 3074de3fbc9S猫头猫 setActiveItem={setActiveItem} 30834588741S猫头猫 itemJustifyContent={itemJustifyContent} 3094de3fbc9S猫头猫 itemHeight={itemHeight} 3104de3fbc9S猫头猫 /> 3114de3fbc9S猫头猫 ); 3124de3fbc9S猫头猫 }} 3134de3fbc9S猫头猫 /> 3144de3fbc9S猫头猫 </View> 3154de3fbc9S猫头猫 ); 3164de3fbc9S猫头猫} 3174de3fbc9S猫头猫 3184de3fbc9S猫头猫interface ISortableFlatListItemProps<T extends any = any> { 3194de3fbc9S猫头猫 item: T; 3204de3fbc9S猫头猫 index: number; 3214de3fbc9S猫头猫 // 高度 3224de3fbc9S猫头猫 itemHeight: number; 32334588741S猫头猫 itemJustifyContent?: 32434588741S猫头猫 | 'flex-start' 32534588741S猫头猫 | 'flex-end' 32634588741S猫头猫 | 'center' 32734588741S猫头猫 | 'space-between' 32834588741S猫头猫 | 'space-around' 32934588741S猫头猫 | 'space-evenly'; 3304de3fbc9S猫头猫 setScrollEnabled: (scrollEnabled: boolean) => void; 3314de3fbc9S猫头猫 renderItem: (props: {item: T; index: number}) => JSX.Element; 3324de3fbc9S猫头猫 setActiveItem: (item: T | null) => void; 3334de3fbc9S猫头猫 activeRef: React.MutableRefObject<number>; 3344de3fbc9S猫头猫} 3354de3fbc9S猫头猫function _SortableFlatListItem(props: ISortableFlatListItemProps) { 3364de3fbc9S猫头猫 const { 3374de3fbc9S猫头猫 itemHeight, 3384de3fbc9S猫头猫 setScrollEnabled, 3394de3fbc9S猫头猫 renderItem, 3404de3fbc9S猫头猫 setActiveItem, 34134588741S猫头猫 itemJustifyContent, 3424de3fbc9S猫头猫 item, 3434de3fbc9S猫头猫 index, 3444de3fbc9S猫头猫 activeRef, 3454de3fbc9S猫头猫 } = props; 3464de3fbc9S猫头猫 3474de3fbc9S猫头猫 // 省一点性能,height是顺着传下来的,放ref就好了 3484de3fbc9S猫头猫 const styleRef = useRef( 3494de3fbc9S猫头猫 StyleSheet.create({ 3504de3fbc9S猫头猫 viewWrapper: { 3514de3fbc9S猫头猫 height: itemHeight, 352c446f2b8S猫头猫 width: '100%', 3534de3fbc9S猫头猫 flexDirection: 'row', 35434588741S猫头猫 justifyContent: itemJustifyContent ?? 'flex-end', 3554de3fbc9S猫头猫 zIndex: defaultZIndex, 3564de3fbc9S猫头猫 }, 3574de3fbc9S猫头猫 btn: { 3584de3fbc9S猫头猫 height: itemHeight, 3594de3fbc9S猫头猫 justifyContent: 'center', 3604de3fbc9S猫头猫 alignItems: 'center', 3613b155a65S猫头猫 position: 'absolute', 3623b155a65S猫头猫 top: 0, 3633b155a65S猫头猫 right: 0, 3643b155a65S猫头猫 width: rpx(100), 3653b155a65S猫头猫 textAlignVertical: 'center', 3664de3fbc9S猫头猫 }, 3674de3fbc9S猫头猫 }), 3684de3fbc9S猫头猫 ); 3694de3fbc9S猫头猫 const textColor = useTextColor(); 3704de3fbc9S猫头猫 3714de3fbc9S猫头猫 return ( 3724de3fbc9S猫头猫 <View style={styleRef.current.viewWrapper}> 3734de3fbc9S猫头猫 {renderItem({item, index})} 3744de3fbc9S猫头猫 <Pressable 3754de3fbc9S猫头猫 onTouchStart={() => { 3764de3fbc9S猫头猫 if (activeRef.current !== -1) { 3774de3fbc9S猫头猫 return; 3784de3fbc9S猫头猫 } 3794de3fbc9S猫头猫 /** 使用ref避免其它组件重新渲染; 由于事件冒泡,这里会先触发 */ 3804de3fbc9S猫头猫 activeRef.current = index; 3814de3fbc9S猫头猫 /** 锁定滚动 */ 3824de3fbc9S猫头猫 setScrollEnabled(false); 3834de3fbc9S猫头猫 setActiveItem(item); 3844de3fbc9S猫头猫 }} 3854de3fbc9S猫头猫 style={styleRef.current.btn}> 3864de3fbc9S猫头猫 <Icon 387*5589cdf3S猫头猫 name="bars-3" 3884de3fbc9S猫头猫 size={iconSizeConst.normal} 3894de3fbc9S猫头猫 color={textColor} 3904de3fbc9S猫头猫 /> 3914de3fbc9S猫头猫 </Pressable> 3924de3fbc9S猫头猫 </View> 3934de3fbc9S猫头猫 ); 3944de3fbc9S猫头猫} 3954de3fbc9S猫头猫 3964de3fbc9S猫头猫const SortableFlatListItem = memo( 3974de3fbc9S猫头猫 _SortableFlatListItem, 3984de3fbc9S猫头猫 (prev, curr) => prev.index === curr.index && prev.item === curr.item, 3994de3fbc9S猫头猫); 4004de3fbc9S猫头猫 4014de3fbc9S猫头猫const FakeFlatListItem = forwardRef(function ( 4024de3fbc9S猫头猫 props: Pick< 4034de3fbc9S猫头猫 ISortableFlatListItemProps, 40434588741S猫头猫 'itemHeight' | 'renderItem' | 'item' | 'itemJustifyContent' 4054de3fbc9S猫头猫 > & { 4064de3fbc9S猫头猫 backgroundColor?: string; 4074de3fbc9S猫头猫 }, 4084de3fbc9S猫头猫 ref: ForwardedRef<View>, 4094de3fbc9S猫头猫) { 41034588741S猫头猫 const {itemHeight, renderItem, item, backgroundColor, itemJustifyContent} = 41134588741S猫头猫 props; 4124de3fbc9S猫头猫 4134de3fbc9S猫头猫 const styleRef = useRef( 4144de3fbc9S猫头猫 StyleSheet.create({ 4154de3fbc9S猫头猫 viewWrapper: { 4164de3fbc9S猫头猫 height: itemHeight, 417c446f2b8S猫头猫 width: '100%', 4184de3fbc9S猫头猫 flexDirection: 'row', 41934588741S猫头猫 justifyContent: itemJustifyContent ?? 'flex-end', 4204de3fbc9S猫头猫 zIndex: defaultZIndex, 4214de3fbc9S猫头猫 }, 4224de3fbc9S猫头猫 btn: { 4234de3fbc9S猫头猫 height: itemHeight, 4244de3fbc9S猫头猫 paddingHorizontal: rpx(28), 4254de3fbc9S猫头猫 justifyContent: 'center', 4264de3fbc9S猫头猫 alignItems: 'center', 4273b155a65S猫头猫 position: 'absolute', 4283b155a65S猫头猫 top: 0, 4293b155a65S猫头猫 right: 0, 4303b155a65S猫头猫 width: rpx(100), 4313b155a65S猫头猫 textAlignVertical: 'center', 4324de3fbc9S猫头猫 }, 4334de3fbc9S猫头猫 }), 4344de3fbc9S猫头猫 ); 4354de3fbc9S猫头猫 const textColor = useTextColor(); 4364de3fbc9S猫头猫 4374de3fbc9S猫头猫 return ( 4384de3fbc9S猫头猫 <View 4394de3fbc9S猫头猫 ref={ref} 4404de3fbc9S猫头猫 style={[ 4414de3fbc9S猫头猫 styleRef.current.viewWrapper, 4424de3fbc9S猫头猫 style.activeItemDefault, 4434de3fbc9S猫头猫 backgroundColor ? {backgroundColor} : {}, 4444de3fbc9S猫头猫 ]}> 4451fbef60aS猫头猫 {item ? renderItem({item, index: -1}) : null} 4464de3fbc9S猫头猫 <Pressable style={styleRef.current.btn}> 4474de3fbc9S猫头猫 <Icon 448*5589cdf3S猫头猫 name="bars-3" 4494de3fbc9S猫头猫 size={iconSizeConst.normal} 4504de3fbc9S猫头猫 color={textColor} 4514de3fbc9S猫头猫 /> 4524de3fbc9S猫头猫 </Pressable> 4534de3fbc9S猫头猫 </View> 4544de3fbc9S猫头猫 ); 4554de3fbc9S猫头猫}); 4564de3fbc9S猫头猫 4574de3fbc9S猫头猫const style = StyleSheet.create({ 4584de3fbc9S猫头猫 activeItemDefault: { 4594de3fbc9S猫头猫 opacity: 0, 4604de3fbc9S猫头猫 zIndex: -1, 4614de3fbc9S猫头猫 position: 'absolute', 4624de3fbc9S猫头猫 top: 0, 4634de3fbc9S猫头猫 left: 0, 4644de3fbc9S猫头猫 }, 4654de3fbc9S猫头猫}); 466