From f4ebdfec3c9e90bccdbcec4c9de0f7c15f9e139f Mon Sep 17 00:00:00 2001 From: Andrei Alecu Date: Fri, 5 Feb 2021 13:28:15 +0200 Subject: [PATCH] feat: dynamic tabbar --- src/MaterialTabBar/TabBar.tsx | 46 ++++++++++++++++++++++++++--------- 1 file changed, 34 insertions(+), 12 deletions(-) diff --git a/src/MaterialTabBar/TabBar.tsx b/src/MaterialTabBar/TabBar.tsx index 41a424db..b8b98c3d 100644 --- a/src/MaterialTabBar/TabBar.tsx +++ b/src/MaterialTabBar/TabBar.tsx @@ -81,11 +81,15 @@ const TabBar = ({ const tabBarRef = useAnimatedRef() const windowWidth = useWindowDimensions().width const isFirstRender = React.useRef(true) - const [nTabs] = React.useState(tabNames.length) - const itemsLayoutGathering = React.useRef([]) + const [itemsLayoutGathering, setItemsLayoutGathering] = React.useState( + new Map() + ) const tabsOffset = useSharedValue(0) const isScrolling = useSharedValue(false) + const nTabs = tabNames.length + + console.log(tabNames) const [itemsLayout, setItemsLayout] = React.useState( scrollEnabled ? [] @@ -110,21 +114,34 @@ const TabBar = ({ }, [scrollEnabled, nTabs, tabNames, windowWidth]) const onTabItemLayout = React.useCallback( - (event: LayoutChangeEvent) => { - if (scrollEnabled && itemsLayout.length < nTabs) { + (event: LayoutChangeEvent, name: T) => { + if (scrollEnabled) { + if (!event.nativeEvent?.layout) return const { width, x } = event.nativeEvent.layout - itemsLayoutGathering.current.push({ - width, - x, + setItemsLayoutGathering((itemsLayoutGathering) => { + const update = new Map(itemsLayoutGathering) + return update.set(name, { + width, + x, + }) }) - if (itemsLayoutGathering.current.length === nTabs) { - setItemsLayout(itemsLayoutGathering.current.sort((a, b) => a.x - b.x)) - } } }, - [scrollEnabled, itemsLayout.length, nTabs] + [scrollEnabled] ) + React.useEffect(() => { + // pick out the layouts for the tabs we know about (in case they changed dynamically) + const layout = [...itemsLayoutGathering.entries()] + .filter(([tabName]) => tabNames.includes(tabName)) + .map(([, layout]) => layout) + .sort((a, b) => a.x - b.x) + + if (layout.length === tabNames.length) { + setItemsLayout(layout) + } + }, [itemsLayoutGathering, tabNames]) + const cancelNextScrollSync = useSharedValue(index.value) const onScroll = useAnimatedScrollHandler( @@ -207,7 +224,11 @@ const TabBar = ({ name={name} label={tabProps.get(name)?.label || getLabelText(name)} onPress={onTabPress} - onLayout={scrollEnabled ? onTabItemLayout : undefined} + onLayout={ + scrollEnabled + ? (event) => onTabItemLayout(event, name) + : undefined + } scrollEnabled={scrollEnabled} indexDecimal={indexDecimal} labelStyle={labelStyle} @@ -239,3 +260,4 @@ const styles = StyleSheet.create({ export { TabBar as MaterialTabBar } export default TabBar + \ No newline at end of file