Guest User

Untitled

a guest
Aug 17th, 2018
80
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.24 KB | None | 0 0
  1. import React, { Component } from 'react';
  2. import {
  3. ActivityIndicator,
  4. Platform,
  5. StyleSheet,
  6. Text,
  7. TouchableHighlight,
  8. TouchableNativeFeedback,
  9. View
  10. } from 'react-native';
  11. import Animated, { Easing } from 'react-native-reanimated';
  12.  
  13. const {
  14. set,
  15. interpolate,
  16. cond,
  17. startClock,
  18. stopClock,
  19. clockRunning,
  20. block,
  21. timing,
  22. debug,
  23. Value,
  24. Clock,
  25. } = Animated;
  26.  
  27.  
  28. const Spinner = () =>
  29. <View style={spinnerStyle.main}>
  30. <ActivityIndicator/>
  31. </View>;
  32.  
  33. const magicVal = 1.4142133;
  34.  
  35. const spinnerStyle = StyleSheet.create({
  36. main: {
  37. backgroundColor: '#1b9779',
  38. width: 70,
  39. justifyContent: 'center',
  40. alignItems: 'center',
  41. height: 70,
  42. borderRadius: 35
  43. }
  44. });
  45.  
  46. const ButtonWrapper = Platform.OS === 'android' ? TouchableNativeFeedback : TouchableHighlight;
  47.  
  48.  
  49. function runTiming(clock, value, dest) {
  50. const state = {
  51. finished: new Value(0),
  52. position: new Value(0),
  53. time: new Value(0),
  54. frameTime: new Value(0),
  55. };
  56.  
  57. const config = {
  58. duration: 1000,
  59. toValue: new Value(0),
  60. easing: Easing.inOut(Easing.ease),
  61. };
  62.  
  63. return block([
  64. cond(clockRunning(clock), 0, [
  65. set(state.finished, 0),
  66. set(state.time, 0),
  67. set(state.position, value),
  68. set(state.frameTime, 0),
  69. set(config.toValue, dest),
  70. startClock(clock),
  71. ]),
  72. timing(clock, state, config),
  73. cond(state.finished, debug('stop clock', stopClock(clock))),
  74. state.position,
  75. ]);
  76. }
  77.  
  78. class Loadable extends React.Component {
  79. constructor(props) {
  80. super(props);
  81. if (props.isLoading) {
  82. console.warn('Should not load at the very beginning');
  83. }
  84. this.state = {
  85. hiding: false,
  86. showing: false
  87. };
  88. }
  89.  
  90. _spinnerWidth = new Value(0);
  91. _spinnerHeight = new Value(0);
  92. _buttonWidth = new Value(0);
  93. _buttonHeight = new Value(0);
  94. _trans = runTiming(new Clock(), 0, 1);
  95.  
  96. _onLayoutSpinner = event => {
  97. const { width, height } = event.nativeEvent.layout;
  98. this._spinnerHeight = height;
  99. this._spinnerWidth = width;
  100. };
  101.  
  102. _onLayoutButton = event => {
  103. const { width, height } = event.nativeEvent.layout;
  104. this._buttonHeight = height;
  105. this._buttonWidth = width;
  106. };
  107.  
  108. shouldComponentUpdate(newProps) {
  109. if (!this.props.isLoading && newProps.isLoading) {
  110. this.setState({
  111. hiding: false,
  112. showing: true
  113. });
  114. }
  115. if (this.props.isLoading && !newProps.isLoading) {
  116. this.setState({
  117. hiding: true,
  118. showing: false
  119. });
  120. }
  121. return true;
  122. }
  123.  
  124. renderButtonWrapper = (disabled = false) =>
  125. <ButtonWrapper
  126. disabled={disabled}
  127. style={{ borderRadius: 5 }}
  128. onPress={this.props.onPress}
  129. >
  130. {this.props.renderButton()}
  131. </ButtonWrapper>;
  132.  
  133. render() {
  134. return (
  135. <View style={styles.container}>
  136. {!this.state.showing && !this.state.hiding &&
  137. <View style={styles.box}>
  138. <View onLayout={this._onLayoutSpinner} style={{
  139. position: 'absolute',
  140. opacity: 0
  141. }}>
  142. {this.props.renderLoading()}
  143. </View>
  144. <View onLayout={this._onLayoutButton} style={{
  145. position: 'absolute',
  146. justifyContent: 'center',
  147. alignItems: 'center',
  148. }}>
  149. {this.renderButtonWrapper()}
  150. </View>
  151. </View>
  152. }
  153.  
  154. {this.state.showing &&
  155. <View style={styles.box}>
  156. <Animated.View style={{
  157. position: 'absolute',
  158. opacity: interpolate(this._trans, {
  159. inputRange: [0.4, 1],
  160. outputRange: [0, 1]
  161. }),
  162. }}>
  163. {this.props.renderLoading()}
  164. </Animated.View>
  165. <Animated.View style={{
  166. position: 'absolute',
  167. justifyContent: 'center',
  168. alignItems: 'center',
  169. borderRadius: interpolate(this._trans, {
  170. inputRange: [0.3, 0.6],
  171. outputRange: [4, this._spinnerWidth * magicVal]
  172. }),
  173. width: interpolate(this._trans, {
  174. inputRange: [0.2, 0.5, 1],
  175. outputRange: [this._buttonWidth, this._spinnerWidth, this._spinnerWidth]
  176. }),
  177. height: interpolate(this._trans, {
  178. inputRange: [0, 0.6, 1],
  179. outputRange: [this._buttonHeight, this._spinnerHeight, this._spinnerHeight]
  180. }),
  181. overflow: 'hidden',
  182. opacity: interpolate(this._trans, {
  183. inputRange: [0.6, 1],
  184. outputRange: [1, 0]
  185. }),
  186. }}>
  187. {this.renderButtonWrapper(true)}
  188. </Animated.View>
  189. </View>
  190. }
  191. {this.state.hiding &&
  192. <View style={styles.box}>
  193. <Animated.View style={{
  194. position: 'absolute',
  195. opacity: interpolate(this._trans, {
  196. inputRange: [0, 0.3],
  197. outputRange: [1, 0]
  198. }),
  199. }}>
  200. {this.props.renderLoading()}
  201. </Animated.View>
  202. <Animated.View style={{
  203. position: 'absolute',
  204. justifyContent: 'center',
  205. alignItems: 'center',
  206. borderRadius: interpolate(this._trans, {
  207. inputRange: [0, 0.4, 0.7],
  208. outputRange: [this._spinnerWidth * magicVal, this._spinnerWidth * magicVal, 4]
  209. }),
  210. width: interpolate(this._trans, {
  211. inputRange: [0, 0.2, 0.5, 1],
  212. outputRange: [this._spinnerWidth, this._spinnerWidth, this._buttonWidth, this._buttonWidth]
  213. }),
  214. height: interpolate(this._trans, {
  215. inputRange: [0, 0.6, 1],
  216. outputRange: [this._spinnerHeight, this._buttonHeight, this._buttonHeight]
  217. }),
  218. overflow: 'hidden',
  219. opacity: interpolate(this._trans, {
  220. inputRange: [0, 0.45, 1],
  221. outputRange: [0, 1, 1]
  222. }),
  223. }}>
  224. {this.renderButtonWrapper()}
  225. </Animated.View>
  226. </View>
  227. }
  228. </View>
  229. );
  230. }
  231. }
  232.  
  233. export default class Example extends React.Component {
  234. state = {
  235. isLoading: false
  236. };
  237. _timeout;
  238.  
  239. componentWillUnmount() {
  240. clearTimeout(this._timeout);
  241. }
  242.  
  243. renderButton = () =>
  244. <View style={styles.button}>
  245. <Text style={{ color: 'white' }}>
  246. Press me press me say that you pres me
  247. </Text>
  248. </View>;
  249.  
  250. renderLoading = () =>
  251. <Spinner/>;
  252.  
  253. render() {
  254. return (
  255. <View style={styles.container}>
  256. <Loadable
  257. onPress={() => {
  258. clearTimeout(this._timeout);
  259. this.setState({ isLoading: true });
  260. this._timeout = setTimeout(() => this.setState({ isLoading: false }), 5000);
  261. }}
  262. isLoading={this.state.isLoading}
  263. renderButton={this.renderButton}
  264. renderLoading={this.renderLoading}
  265. />
  266. </View>
  267. );
  268. }
  269. }
  270.  
  271. const styles = StyleSheet.create({
  272. button: {
  273. borderRadius: 5,
  274. backgroundColor: '#3167ff',
  275. justifyContent: 'center',
  276. alignItems: 'center',
  277. width: 220,
  278. height: 100
  279. },
  280. container: {
  281. flex: 1,
  282. justifyContent: 'center',
  283. alignItems: 'center',
  284. backgroundColor: 'white',
  285. },
  286. box: {
  287. justifyContent: 'center',
  288. alignItems: 'center',
  289. },
  290.  
  291. box2: {
  292. width: 20,
  293. height: 60,
  294. backgroundColor: 'red',
  295. marginBottom: 40
  296. }
  297. });
Add Comment
Please, Sign In to add comment