Skip to content
This repository has been archived by the owner on Nov 27, 2022. It is now read-only.

Commit

Permalink
feat: add renderTabBarItem prop to TabBar
Browse files Browse the repository at this point in the history
  • Loading branch information
jtomaszewski authored and satya164 committed Jul 15, 2020
1 parent 02b08e2 commit 33fd808
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 46 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -527,6 +527,10 @@ Function which takes an object with the current route, focused status and color
/>
```

##### `renderTabBarItem`

Function which takes a `TabBarItemProps` object and returns a custom React Element to be used as a tab button.

##### `renderIndicator`

Function which takes an object with the current route and returns a custom React Element to be used as a tab indicator.
Expand Down
98 changes: 53 additions & 45 deletions src/TabBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
Platform,
} from 'react-native';
import Animated from 'react-native-reanimated';
import TabBarItem from './TabBarItem';
import TabBarItem, { Props as TabBarItemProps } from './TabBarItem';
import TabBarIndicator, { Props as IndicatorProps } from './TabBarIndicator';
import memoize from './memoize';
import {
Expand Down Expand Up @@ -49,6 +49,9 @@ export type Props<T extends Route> = SceneRendererProps & {
) => React.ReactNode;
renderBadge?: (scene: Scene<T>) => React.ReactNode;
renderIndicator: (props: IndicatorProps<T>) => React.ReactNode;
renderTabBarItem?: (
props: TabBarItemProps<T> & { key: string }
) => React.ReactElement;
onTabPress?: (scene: Scene<T> & Event) => void;
onTabLongPress?: (scene: Scene<T>) => void;
tabStyle?: StyleProp<ViewStyle>;
Expand Down Expand Up @@ -310,6 +313,7 @@ export default class TabBar<T extends Route> extends React.Component<
renderBadge,
renderIcon,
renderLabel,
renderTabBarItem,
activeColor,
inactiveColor,
pressColor,
Expand Down Expand Up @@ -400,45 +404,43 @@ export default class TabBar<T extends Route> extends React.Component<
this.scrollView = el?.getNode();
}}
>
{routes.map((route: T) => (
<TabBarItem
onLayout={
isWidthDynamic
? (e) => {
this.measuredTabWidths[route.key] =
e.nativeEvent.layout.width;

// When we have measured widths for all of the tabs, we should updates the state
// We avoid doing separate setState for each layout since it triggers multiple renders and slows down app
if (
routes.every(
(r) =>
typeof this.measuredTabWidths[r.key] === 'number'
)
) {
this.setState({
tabWidths: { ...this.measuredTabWidths },
});
}
{routes.map((route: T) => {
const props: TabBarItemProps<T> & { key: string } = {
key: route.key,
position: position,
route: route,
navigationState: navigationState,
getAccessibilityLabel: getAccessibilityLabel,
getAccessible: getAccessible,
getLabelText: getLabelText,
getTestID: getTestID,
renderBadge: renderBadge,
renderIcon: renderIcon,
renderLabel: renderLabel,
activeColor: activeColor,
inactiveColor: inactiveColor,
pressColor: pressColor,
pressOpacity: pressOpacity,
onLayout: isWidthDynamic
? (e) => {
this.measuredTabWidths[route.key] =
e.nativeEvent.layout.width;

// When we have measured widths for all of the tabs, we should updates the state
// We avoid doing separate setState for each layout since it triggers multiple renders and slows down app
if (
routes.every(
(r) =>
typeof this.measuredTabWidths[r.key] === 'number'
)
) {
this.setState({
tabWidths: { ...this.measuredTabWidths },
});
}
: undefined
}
key={route.key}
position={position}
route={route}
navigationState={navigationState}
getAccessibilityLabel={getAccessibilityLabel}
getAccessible={getAccessible}
getLabelText={getLabelText}
getTestID={getTestID}
renderBadge={renderBadge}
renderIcon={renderIcon}
renderLabel={renderLabel}
activeColor={activeColor}
inactiveColor={inactiveColor}
pressColor={pressColor}
pressOpacity={pressOpacity}
onPress={() => {
}
: undefined,
onPress: () => {
const event: Scene<T> & Event = {
route,
defaultPrevented: false,
Expand All @@ -454,12 +456,18 @@ export default class TabBar<T extends Route> extends React.Component<
}

this.props.jumpTo(route.key);
}}
onLongPress={() => onTabLongPress?.({ route })}
labelStyle={labelStyle}
style={tabStyle}
/>
))}
},
onLongPress: () => onTabLongPress?.({ route }),
labelStyle: labelStyle,
style: tabStyle,
};

return renderTabBarItem ? (
renderTabBarItem(props)
) : (
<TabBarItem {...props} />
);
})}
</Animated.ScrollView>
</View>
</Animated.View>
Expand Down
2 changes: 1 addition & 1 deletion src/TabBarItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import memoize from './memoize';
// @ts-ignore
const AnimatedInterpolate = Animated.interpolateNode || Animated.interpolate;

type Props<T extends Route> = {
export type Props<T extends Route> = {
position: Animated.Node<number>;
route: T;
navigationState: NavigationState<T>;
Expand Down
5 changes: 5 additions & 0 deletions src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ export type { Props as TabViewProps } from './TabView';
export { default as TabBarIndicator } from './TabBarIndicator';
export type { Props as TabBarIndicatorProps } from './TabBarIndicator';

export { default as TabBarItem } from './TabBarItem';
export type { Props as TabBarItemProps } from './TabBarItem';

export { default as TouchableItem } from './TouchableItem';

export { default as SceneMap } from './SceneMap';
export { default as ScrollPager } from './ScrollPager';

Expand Down

0 comments on commit 33fd808

Please sign in to comment.