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

Commit 20b5062

Browse files
authored
refactor: use FlatList instead of ScrollView for the TabBar (#1386)
1 parent 69cbb62 commit 20b5062

File tree

1 file changed

+36
-22
lines changed

1 file changed

+36
-22
lines changed

src/TabBar.tsx

Lines changed: 36 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,14 @@ import {
33
Animated,
44
StyleSheet,
55
View,
6-
ScrollView,
76
StyleProp,
87
ViewStyle,
98
TextStyle,
109
LayoutChangeEvent,
1110
I18nManager,
1211
Platform,
12+
FlatList,
13+
ListRenderItemInfo,
1314
} from 'react-native';
1415
import TabBarItem, { Props as TabBarItemProps } from './TabBarItem';
1516
import TabBarIndicator, { Props as IndicatorProps } from './TabBarIndicator';
@@ -131,7 +132,7 @@ export default class TabBar<T extends Route> extends React.Component<
131132

132133
private scrollAmount = new Animated.Value(0);
133134

134-
private scrollViewRef = React.createRef<ScrollView>();
135+
private flatListRef = React.createRef<FlatList>();
135136

136137
private getFlattenedTabWidth = (style: StyleProp<ViewStyle>) => {
137138
const tabStyle = StyleSheet.flatten(style);
@@ -166,7 +167,6 @@ export default class TabBar<T extends Route> extends React.Component<
166167
if (scrollEnabled) {
167168
return (layout.width / 5) * 2;
168169
}
169-
170170
return layout.width / routes.length;
171171
};
172172

@@ -248,8 +248,8 @@ export default class TabBar<T extends Route> extends React.Component<
248248

249249
private resetScroll = (index: number) => {
250250
if (this.props.scrollEnabled) {
251-
this.scrollViewRef.current?.scrollTo({
252-
x: this.getScrollAmount(this.props, this.state, index),
251+
this.flatListRef.current?.scrollToOffset({
252+
offset: this.getScrollAmount(this.props, this.state, index),
253253
animated: true,
254254
});
255255
}
@@ -367,7 +367,9 @@ export default class TabBar<T extends Route> extends React.Component<
367367
})}
368368
</Animated.View>
369369
<View style={styles.scroll}>
370-
<Animated.ScrollView
370+
<Animated.FlatList
371+
data={routes as Animated.WithAnimatedValue<T>[]}
372+
keyExtractor={(item) => item.key}
371373
horizontal
372374
accessibilityRole="tablist"
373375
keyboardShouldPersistTaps="handled"
@@ -392,19 +394,7 @@ export default class TabBar<T extends Route> extends React.Component<
392394
contentContainerStyle,
393395
]}
394396
scrollEventThrottle={16}
395-
onScroll={Animated.event(
396-
[
397-
{
398-
nativeEvent: {
399-
contentOffset: { x: this.scrollAmount },
400-
},
401-
},
402-
],
403-
{ useNativeDriver: true }
404-
)}
405-
ref={this.scrollViewRef}
406-
>
407-
{routes.map((route: T, index) => {
397+
renderItem={({ item: route, index }: ListRenderItemInfo<T>) => {
408398
const props: TabBarItemProps<T> & { key: string } = {
409399
key: route.key,
410400
position: position,
@@ -459,7 +449,20 @@ export default class TabBar<T extends Route> extends React.Component<
459449
},
460450
onLongPress: () => onTabLongPress?.({ route }),
461451
labelStyle: labelStyle,
462-
style: tabStyle,
452+
style: [
453+
tabStyle,
454+
// Calculate the deafult width for tab for FlatList to work.
455+
this.getFlattenedTabWidth(tabStyle) === undefined && {
456+
width: this.getComputedTabWidth(
457+
index,
458+
layout,
459+
routes,
460+
scrollEnabled,
461+
tabWidths,
462+
this.getFlattenedTabWidth(tabStyle)
463+
),
464+
},
465+
],
463466
};
464467

465468
return (
@@ -472,8 +475,19 @@ export default class TabBar<T extends Route> extends React.Component<
472475
)}
473476
</React.Fragment>
474477
);
475-
})}
476-
</Animated.ScrollView>
478+
}}
479+
onScroll={Animated.event(
480+
[
481+
{
482+
nativeEvent: {
483+
contentOffset: { x: this.scrollAmount },
484+
},
485+
},
486+
],
487+
{ useNativeDriver: true }
488+
)}
489+
ref={this.flatListRef}
490+
/>
477491
</View>
478492
</Animated.View>
479493
);

0 commit comments

Comments
 (0)