Application Android et IOS pour l'amicale des élèves https://play.google.com/store/apps/details?id=fr.amicaleinsat.application
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

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