설명 없음

index.ios.js 4.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. 'use strict'
  2. import React, {
  3. Component,
  4. PropTypes
  5. } from 'react';
  6. import {
  7. Animated,
  8. Dimensions,
  9. View,
  10. WebView
  11. } from 'react-native';
  12. import ImmutableComponent from 'react-immutable-component';
  13. export default class AutoHeightWebView extends ImmutableComponent {
  14. constructor(props) {
  15. super(props);
  16. this.handleNavigationStateChange = this.handleNavigationStateChange.bind(this);
  17. if (this.props.enableAnimation) {
  18. this.opacityAnimatedValue = new Animated.Value(0);
  19. }
  20. const initialScript = props.files ? this.appendFilesToHead(props.files, BaseScript) : BaseScript;
  21. this.state = {
  22. height: 0,
  23. script: initialScript
  24. };
  25. }
  26. componentWillReceiveProps(nextProps) {
  27. let currentScript = BaseScript;
  28. if (nextProps.files) {
  29. currentScript = this.appendFilesToHead(nextProps.files, BaseScript);
  30. }
  31. this.setState({ script: currentScript });
  32. }
  33. appendFilesToHead(files, script) {
  34. if (!files) {
  35. return script;
  36. }
  37. for (let file of files) {
  38. script =
  39. `
  40. var link = document.createElement('link');
  41. link.rel = '` + file.rel + `';
  42. link.type = '` + file.type + `';
  43. link.href = '` + file.href + `';
  44. document.head.appendChild(link);
  45. `+ script;
  46. }
  47. return script;
  48. }
  49. onHeightUpdated(height) {
  50. if (this.props.onHeightUpdated) {
  51. this.props.onHeightUpdated(height);
  52. }
  53. }
  54. handleNavigationStateChange(navState) {
  55. const height = Number(navState.title);
  56. if (height) {
  57. if (this.props.enableAnimation) {
  58. this.opacityAnimatedValue.setValue(0);
  59. }
  60. this.setState({ height }, () => {
  61. if (this.props.enableAnimation) {
  62. Animated.timing(this.opacityAnimatedValue, {
  63. toValue: 1,
  64. duration: this.props.animationDuration
  65. }).start(() => this.onHeightUpdated(height));
  66. }
  67. else {
  68. this.onHeightUpdated(height);
  69. }
  70. });
  71. }
  72. }
  73. render() {
  74. const { height, script } = this.state;
  75. const { enableAnimation, source, heightOffset, customScript, style } = this.props;
  76. const webViewSource = Object.assign({}, source, { baseUrl: 'web/' });
  77. return (
  78. <Animated.View style={[{
  79. opacity: enableAnimation ? this.opacityAnimatedValue : 1,
  80. width: ScreenWidth,
  81. height: height + heightOffset,
  82. backgroundColor: 'transparent'
  83. }, style]}>
  84. <WebView
  85. style={{
  86. flex: 1,
  87. backgroundColor: 'transparent'
  88. }}
  89. injectedJavaScript={script + customScript}
  90. scrollEnabled={false}
  91. source={webViewSource}
  92. onNavigationStateChange={this.handleNavigationStateChange} />
  93. </Animated.View>
  94. );
  95. }
  96. }
  97. AutoHeightWebView.propTypes = {
  98. enableAnimation: PropTypes.bool,
  99. // only works on enable animation
  100. animationDuration: PropTypes.number,
  101. source: WebView.propTypes.source,
  102. onHeightUpdated: PropTypes.func,
  103. customScript: PropTypes.string,
  104. // offset rn webview margin
  105. heightOffset: PropTypes.number,
  106. style: View.propTypes.style,
  107. // add web/files... to project root
  108. files: PropTypes.arrayOf(PropTypes.shape({
  109. href: PropTypes.string,
  110. type: PropTypes.string,
  111. rel: PropTypes.string
  112. }))
  113. }
  114. AutoHeightWebView.defaultProps = {
  115. animationDuration: 555,
  116. heightOffset: 12
  117. }
  118. const ScreenWidth = Dimensions.get('window').width;
  119. const BaseScript =
  120. `
  121. ; (function () {
  122. var wrapper = document.createElement('div');
  123. wrapper.id = 'height-wrapper';
  124. while (document.body.firstChild) {
  125. wrapper.appendChild(document.body.firstChild);
  126. }
  127. document.body.appendChild(wrapper);
  128. var i = 0;
  129. function updateHeight() {
  130. document.title = wrapper.clientHeight;
  131. window.location.hash = ++i;
  132. }
  133. updateHeight();
  134. window.addEventListener('load', updateHeight);
  135. window.addEventListener('resize', updateHeight);
  136. } ());
  137. `;