Application Android et IOS pour l'amicale des élèves
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

CustomTabBar.js 5.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. import * as React from 'react';
  2. import {withTheme} from 'react-native-paper';
  3. import TabIcon from "./TabIcon";
  4. import TabHomeIcon from "./TabHomeIcon";
  5. import {Animated} from 'react-native';
  6. import {Collapsible} from "react-navigation-collapsible";
  7. type Props = {
  8. state: Object,
  9. descriptors: Object,
  10. navigation: Object,
  11. theme: Object,
  12. collapsibleStack: Object,
  13. }
  14. type State = {
  15. translateY: AnimatedValue,
  16. barSynced: boolean,
  17. }
  18. const TAB_ICONS = {
  19. proxiwash: 'tshirt-crew',
  20. services: 'account-circle',
  21. planning: 'calendar-range',
  22. planex: 'clock',
  23. };
  24. class CustomTabBar extends React.Component<Props, State> {
  25. static TAB_BAR_HEIGHT = 48;
  26. state = {
  27. translateY: new Animated.Value(0),
  28. }
  29. syncTabBar = (route, index) => {
  30. const state = this.props.state;
  31. const isFocused = state.index === index;
  32. if (isFocused) {
  33. const stackState = route.state;
  34. const stackRoute = stackState ? stackState.routes[stackState.index] : undefined;
  35. const params: { collapsible: Collapsible } = stackRoute ? stackRoute.params : undefined;
  36. const collapsible = params ? params.collapsible : undefined;
  37. if (collapsible) {
  38. this.setState({
  39. translateY: Animated.multiply(-1.5, collapsible.translateY), // Hide tab bar faster than header bar
  40. });
  41. }
  42. }
  43. };
  44. /**
  45. * Navigates to the given route if it is different from the current one
  46. *
  47. * @param route Destination route
  48. * @param currentIndex The current route index
  49. * @param destIndex The destination route index
  50. */
  51. onItemPress(route: Object, currentIndex: number, destIndex: number) {
  52. const event = this.props.navigation.emit({
  53. type: 'tabPress',
  54. target: route.key,
  55. canPreventDefault: true,
  56. });
  57. if (currentIndex !== destIndex && !event.defaultPrevented)
  58. this.props.navigation.navigate(route.name);
  59. }
  60. /**
  61. * Navigates to tetris screen on home button long press
  62. *
  63. * @param route
  64. */
  65. onItemLongPress(route: Object) {
  66. const event = this.props.navigation.emit({
  67. type: 'tabLongPress',
  68. target: route.key,
  69. canPreventDefault: true,
  70. });
  71. if (route.name === "home" && !event.defaultPrevented)
  72. this.props.navigation.navigate('game-start');
  73. }
  74. /**
  75. * Gets an icon for the given route if it is not the home one as it uses a custom button
  76. *
  77. * @param route
  78. * @param focused
  79. * @returns {null}
  80. */
  81. tabBarIcon = (route, focused) => {
  82. let icon = TAB_ICONS[route.name];
  83. icon = focused ? icon : icon + ('-outline');
  84. if (route.name !== "home")
  85. return icon;
  86. else
  87. return null;
  88. };
  89. /**
  90. * Finds the active route and syncs the tab bar animation with the header bar
  91. */
  92. onRouteChange = () => {
  93. this.props.state.routes.map(this.syncTabBar)
  94. }
  95. /**
  96. * Gets a tab icon render.
  97. * If the given route is focused, it syncs the tab bar and header bar animations together
  98. *
  99. * @param route The route for the icon
  100. * @param index The index of the current route
  101. * @returns {*}
  102. */
  103. renderIcon = (route, index) => {
  104. const state = this.props.state;
  105. const {options} = this.props.descriptors[route.key];
  106. const label =
  107. options.tabBarLabel != null
  108. ? options.tabBarLabel
  109. : options.title != null
  110. ? options.title
  111. : route.name;
  112. const onPress = () => this.onItemPress(route, state.index, index);
  113. const onLongPress = () => this.onItemLongPress(route);
  114. const isFocused = state.index === index;
  115. const color = isFocused ? this.props.theme.colors.primary : this.props.theme.colors.tabIcon;
  116. if (route.name !== "home") {
  117. return <TabIcon
  118. onPress={onPress}
  119. onLongPress={onLongPress}
  120. icon={this.tabBarIcon(route, isFocused)}
  121. color={color}
  122. label={label}
  123. focused={isFocused}
  124. extraData={state.index > index}
  125. key={route.key}
  126. />
  127. } else
  128. return <TabHomeIcon
  129. onPress={onPress}
  130. onLongPress={onLongPress}
  131. focused={isFocused}
  132. key={route.key}
  133. tabBarHeight={CustomTabBar.TAB_BAR_HEIGHT}
  134. />
  135. };
  136. getIcons() {
  137. return this.props.state.routes.map(this.renderIcon);
  138. }
  139. render() {
  140. this.props.navigation.addListener('state', this.onRouteChange);
  141. const icons = this.getIcons();
  142. return (
  143. <Animated.View
  144. useNativeDriver
  145. style={{
  146. flexDirection: 'row',
  147. height: CustomTabBar.TAB_BAR_HEIGHT,
  148. width: '100%',
  149. position: 'absolute',
  150. bottom: 0,
  151. left: 0,
  152. backgroundColor: this.props.theme.colors.surface,
  153. transform: [{translateY: this.state.translateY}],
  154. }}
  155. >
  156. {icons}
  157. </Animated.View>
  158. );
  159. }
  160. }
  161. export default withTheme(CustomTabBar);