import React from 'react'; import { FC, useState } from 'react'; import { View, ViewProps } from 'react-native'; import Space from '../Space'; import Col from '../Col'; import Row from '../Row'; import { AutoLayoutProps } from './interface'; import { useMeasureTextSize } from './useMeasureTextWidth'; import ShouldRender from '../ShouldRender'; import { THEME_TOKEN } from '../Theme/constant'; import { isNumber } from 'lodash'; const defaultGetMaxSingleWidthLimit = (wrapWidth: number) => { return Math.floor( (wrapWidth - 2 * THEME_TOKEN['--spacing-3'] - THEME_TOKEN['--spacing-2']) / 2 - THEME_TOKEN['--font-size-3'] ); }; export const AutoLayout: FC = ({ components, direction, columnReverse = true, verticalGap = THEME_TOKEN['--spacing-3'], horizontalGap = THEME_TOKEN['--spacing-2'], wrapStyle, getMaxSingleWidthLimit = defaultGetMaxSingleWidthLimit, }) => { const [wrapWidth, setWrapWidth] = useState(0); const nonEmptyComponents = (components || []).filter(Boolean); const [component1, component2] = nonEmptyComponents; const { width: component2Width, HiddenText: component2HiddenText } = useMeasureTextSize(component2); const { width: component1Width, HiddenText: component1HiddenText } = useMeasureTextSize(component1); const getCanShowComponents = () => { try { if ( component2 && isNumber(component2Width) && component1 && isNumber(component1Width) ) { return true; } if (component2 && isNumber(component2Width) && !component1) { return true; } if (component1 && isNumber(component1Width) && !component2) { return true; } if (nonEmptyComponents?.length > 2) { return true; } return false; } catch (error) { return true; } }; const canShowComponents = getCanShowComponents(); const onWrapLayout: ViewProps['onLayout'] = (event) => { const width = event.nativeEvent.layout.width; setWrapWidth(width); }; const getAutoCalculatedDirection = () => { try { if (wrapWidth <= 0) { return 'row'; } if (nonEmptyComponents?.length > 2) { return 'column'; } const longestComponentWidth = Math.max( component2Width || 0, component1Width || 0 ); const maxSingleWidthLimit = getMaxSingleWidthLimit(wrapWidth); // 如果任一按钮宽度超过最大可用宽度,使用 column 布局 const shouldCalculate = canShowComponents && maxSingleWidthLimit > 0 && longestComponentWidth >= maxSingleWidthLimit; if (shouldCalculate) { return 'column'; } return 'row'; } catch (error) { return 'row'; } }; const autoCalculatedDirection = getAutoCalculatedDirection(); // 使用用户指定的方向,如果没有则使用自动计算的方向 const computedDirection = direction || autoCalculatedDirection; const getRenderComponents = () => { let renderComponents = nonEmptyComponents; if (computedDirection === 'column' && columnReverse) { renderComponents = [...renderComponents].reverse(); } return renderComponents; }; const renderComponents = getRenderComponents(); const renderSingle = () => { return renderComponents?.[0]; }; const renderMulti = () => { return computedDirection === 'column' ? ( {renderComponents} ) : ( {renderComponents.map((button, i) => ( {button} ))} ); }; return ( {renderComponents.length > 1 ? renderMulti() : renderSingle()} {component2HiddenText} {component1HiddenText} ); };