iou90 5 年 前
コミット
819b4c7275
共有5 個のファイルを変更した145 個の追加142 個の削除を含む
  1. 4
    4
      android/build.gradle
  2. 23
    25
      autoHeightWebView/common.js
  3. 105
    108
      autoHeightWebView/index.android.js
  4. 4
    4
      demo/android/app/build.gradle
  5. 9
    1
      demo/android/build.gradle

+ 4
- 4
android/build.gradle ファイルの表示

@@ -1,12 +1,12 @@
1 1
 apply plugin: 'com.android.library'
2 2
 
3 3
 android {
4
-    compileSdkVersion 23
5
-    buildToolsVersion "23.0.1"
4
+    compileSdkVersion 26
5
+    buildToolsVersion "27.0.3"
6 6
 
7 7
     defaultConfig {
8 8
         minSdkVersion 16
9
-        targetSdkVersion 22
9
+        targetSdkVersion 26
10 10
         versionCode 1
11 11
         versionName "1.0"
12 12
 
@@ -26,7 +26,7 @@ dependencies {
26 26
     androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
27 27
         exclude group: 'com.android.support', module: 'support-annotations'
28 28
     })
29
-    compile 'com.android.support:appcompat-v7:23.0.1'
29
+    compile 'com.android.support:appcompat-v7:26.1.0'
30 30
     compile "com.facebook.react:react-native:+"  // From node_modules
31 31
     testCompile 'junit:junit:4.12'
32 32
 }

+ 23
- 25
autoHeightWebView/common.js ファイルの表示

@@ -23,10 +23,6 @@ function appendFilesToHead(files, script) {
23 23
 
24 24
 const screenWidth = Dimensions.get('window').width;
25 25
 
26
-function getWidth(style) {
27
-  return style && style.width ? style.width : screenWidth;
28
-}
29
-
30 26
 const bodyStyle = `
31 27
 body {
32 28
   margin: 0;
@@ -62,20 +58,6 @@ function isChanged(newValue, oldValue) {
62 58
   return !Immutable.is(Immutable.fromJS(newValue), Immutable.fromJS(oldValue));
63 59
 }
64 60
 
65
-function getScript(props, getBaseScript, getIframeBaseScript) {
66
-  const { hasIframe, files, customStyle, customScript, style } = getReloadRelatedData(props);
67
-  const baseScript = getBaseScript(style);
68
-  let script = hasIframe ? baseScript : getIframeBaseScript(style);
69
-  script = files ? appendFilesToHead(files, baseScript) : baseScript;
70
-  script = appendStylesToHead(customStyle, script);
71
-  customScript && (script = customScript + script);
72
-  return script;
73
-}
74
-
75
-function isEqual(newProps, oldProps) {
76
-  return isChanged(getReloadRelatedData(newProps), getReloadRelatedData(oldProps));
77
-}
78
-
79 61
 function insertStringAfterAnotherString(raw, searchValue, insertValue) {
80 62
   const position = raw.indexOf(searchValue) + searchValue.length;
81 63
   return [raw.slice(0, position), insertValue, raw.slice(position)].join('');
@@ -97,7 +79,25 @@ function getInjectedSource(html, script) {
97 79
   }
98 80
 }
99 81
 
100
-function setState(props, getBaseScript, getIframeBaseScript) {
82
+export function getScript(props, getBaseScript, getIframeBaseScript) {
83
+  const { hasIframe, files, customStyle, customScript, style } = getReloadRelatedData(props);
84
+  const baseScript = getBaseScript(style);
85
+  let script = hasIframe ? getIframeBaseScript(style) : baseScript;
86
+  script = files ? appendFilesToHead(files, baseScript) : baseScript;
87
+  script = appendStylesToHead(customStyle, script);
88
+  customScript && (script = customScript + script);
89
+  return script;
90
+}
91
+
92
+export function getWidth(style) {
93
+  return style && style.width ? style.width : screenWidth;
94
+}
95
+
96
+export function isEqual(newProps, oldProps) {
97
+  return isChanged(getReloadRelatedData(newProps), getReloadRelatedData(oldProps));
98
+}
99
+
100
+export function setState(props, getBaseScript, getIframeBaseScript) {
101 101
   const { source, style } = props;
102 102
   const script = getScript(props, getBaseScript, getIframeBaseScript);
103 103
   let state = {
@@ -123,7 +123,7 @@ function setState(props, getBaseScript, getIframeBaseScript) {
123 123
   return state;
124 124
 }
125 125
 
126
-function handleSizeUpdated(height, width, onSizeUpdated) {
126
+export function handleSizeUpdated(height, width, onSizeUpdated) {
127 127
   onSizeUpdated &&
128 128
     onSizeUpdated({
129 129
       height,
@@ -131,7 +131,7 @@ function handleSizeUpdated(height, width, onSizeUpdated) {
131 131
     });
132 132
 }
133 133
 
134
-function getSize(newHeight, newWidth, height, width, updatingSize, calledOnce) {
134
+export function getSize(newHeight, newWidth, height, width, updatingSize, calledOnce) {
135 135
   if (!calledOnce || updatingSize) {
136 136
     return {
137 137
       h: height,
@@ -144,13 +144,11 @@ function getSize(newHeight, newWidth, height, width, updatingSize, calledOnce) {
144 144
   };
145 145
 }
146 146
 
147
-const domMutationObserveScript = `
147
+export const domMutationObserveScript = `
148 148
 var MutationObserver = window.MutationObserver || window.WebKitMutationObserver;
149 149
 var observer = new MutationObserver(updateSize);
150 150
 observer.observe(document, {
151 151
     subtree: true,
152 152
     attributes: true
153 153
 });
154
-`;
155
-
156
-export { isEqual, setState, getWidth, handleSizeUpdated, domMutationObserveScript, getSize };
154
+`;

+ 105
- 108
autoHeightWebView/index.android.js ファイルの表示

@@ -7,7 +7,6 @@ import {
7 7
   requireNativeComponent,
8 8
   Animated,
9 9
   DeviceEventEmitter,
10
-  Dimensions,
11 10
   StyleSheet,
12 11
   Platform,
13 12
   UIManager,
@@ -19,7 +18,7 @@ import PropTypes from 'prop-types';
19 18
 
20 19
 import Immutable from 'immutable';
21 20
 
22
-import { getScript, onHeightUpdated, onWidthUpdated, onHeightWidthUpdated, domMutationObserveScript } from './common.js';
21
+import { handleSizeUpdated, getWidth, getScript, domMutationObserveScript } from './common.js';
23 22
 
24 23
 const RCTAutoHeightWebView = requireNativeComponent('RCTAutoHeightWebView', AutoHeightWebView, {
25 24
   nativeOnly: {
@@ -32,25 +31,22 @@ const RCTAutoHeightWebView = requireNativeComponent('RCTAutoHeightWebView', Auto
32 31
   }
33 32
 });
34 33
 
35
-const screenWidth = Dimensions.get('window').width;
36
-
37 34
 export default class AutoHeightWebView extends PureComponent {
38 35
   static propTypes = {
36
+    onMessage: PropTypes.func,
37
+    scrollEnabled: PropTypes.bool,
39 38
     source: WebView.propTypes.source,
40
-      onHeightUpdated: PropTypes.func,
41
-      onWidthUpdated: PropTypes.func,
42
-      onHeightWidthUpdated: PropTypes.func,
43
-      shouldResizeWidth: PropTypes.bool,
44 39
     customScript: PropTypes.string,
45 40
     customStyle: PropTypes.string,
46 41
     enableAnimation: PropTypes.bool,
42
+    // either height or width updated will trigger this
43
+    onSizeUpdated: PropTypes.func,
47 44
     // if set to false may cause some layout issues (width of container will be than width of screen)
48 45
     scalesPageToFit: PropTypes.bool,
49 46
     // only works on enable animation
50 47
     animationDuration: PropTypes.number,
51 48
     // offset of rn webView margin
52
-      heightOffset: PropTypes.number,
53
-      widthOffset: PropTypes.number,
49
+    heightOffset: PropTypes.number,
54 50
     // baseUrl not work in android 4.3 or below version
55 51
     enableBaseUrl: PropTypes.bool,
56 52
     style: ViewPropTypes.style,
@@ -74,22 +70,21 @@ export default class AutoHeightWebView extends PureComponent {
74 70
     enableBaseUrl: false,
75 71
     enableAnimation: true,
76 72
     animationDuration: 555,
77
-      heightOffset: 20,
78
-      widthOffset: 20,
79
-      shouldResizeWidth: false
73
+    heightOffset: 20
80 74
   };
81 75
 
82 76
   constructor(props) {
83 77
     super(props);
84
-    props.enableAnimation && (this.opacityAnimatedValue = new Animated.Value(0));
78
+    const { enableAnimation, style } = props;
79
+    enableAnimation && (this.opacityAnimatedValue = new Animated.Value(0));
80
+    this.webView = React.createRef();
85 81
     isBelowKitKat && DeviceEventEmitter.addListener('webViewBridgeMessage', this.listenWebViewBridgeMessage);
86 82
     this.state = {
87 83
       isChangingSource: false,
88 84
       height: 0,
89
-        heightOffset: 0,
90
-        width: screenWidth,
91
-        widthOffset: 0,
92
-      script: getScript(props, baseScript)
85
+      heightOffset: 0,
86
+      width: getWidth(style),
87
+      script: getScript(props, getBaseScript)
93 88
     };
94 89
   }
95 90
 
@@ -97,27 +92,25 @@ export default class AutoHeightWebView extends PureComponent {
97 92
     this.startInterval();
98 93
   }
99 94
 
100
-  componentWillReceiveProps(nextProps) {
95
+  UNSAFE_componentWillReceiveProps(nextProps) {
101 96
     // injectedJavaScript only works when webView reload (source changed)
102
-      if (Immutable.is(Immutable.fromJS(this.props.source), Immutable.fromJS(nextProps.source))) {
103
-          return;
104
-      }
105
-      else {
106
-          this.setState(
107
-              {
108
-                  isChangingSource: true,
109
-                  height: 0,
110
-                  heightOffset: 0,
111
-                  width: 0,
112
-                  widthOffset: 0,
113
-              },
114
-              () => {
115
-                  this.startInterval();
116
-                  this.setState({ isChangingSource: false });
117
-              }
118
-          );
119
-      }
120
-    this.setState({ script: getScript(nextProps, baseScript) });
97
+    if (Immutable.is(Immutable.fromJS(this.props.source), Immutable.fromJS(nextProps.source))) {
98
+      return;
99
+    } else {
100
+      this.setState(
101
+        {
102
+          isChangingSource: true,
103
+          height: 0,
104
+          heightOffset: 0,
105
+          width: 0
106
+        },
107
+        () => {
108
+          this.startInterval();
109
+          this.setState({ isChangingSource: false });
110
+        }
111
+      );
112
+    }
113
+    this.setState({ script: getScript(nextProps, getBaseScript) });
121 114
   }
122 115
 
123 116
   componentWillUnmount() {
@@ -160,29 +153,34 @@ export default class AutoHeightWebView extends PureComponent {
160 153
   }
161 154
 
162 155
   onMessage = e => {
163
-      const { height, width } = JSON.parse(isBelowKitKat ? e.nativeEvent.message : e.nativeEvent.data);
164
-      if (height && height !== this.state.height && width && width !== this.state.width) {
165
-          const { enableAnimation, animationDuration, heightOffset, widthOffset } = this.props;
166
-          enableAnimation && this.opacityAnimatedValue.setValue(0);
167
-          this.stopInterval();
168
-          
169
-          this.setState(
170
-              {
171
-                  heightOffset,
172
-                  height,
173
-                  widthOffset,
174
-                  width
175
-              },
176
-              () => {
177
-                  enableAnimation
178
-                      ? Animated.timing(this.opacityAnimatedValue, {
179
-                          toValue: 1,
180
-                          duration: animationDuration
181
-                      }).start(() => onHeightWidthUpdated(height, width, this.props))
182
-                      : onHeightWidthUpdated(height, width, this.props);
183
-              }
184
-          );
185
-      }
156
+    const { height, width } = JSON.parse(isBelowKitKat ? e.nativeEvent.message : e.nativeEvent.data);
157
+    const { height: oldHeight, width: oldWidth } = this.state;
158
+    if ((height && height !== oldHeight) || (width && width !== oldWidth)) {
159
+      const { enableAnimation, animationDuration, heightOffset, onSizeUpdated } = this.props;
160
+      enableAnimation && this.opacityAnimatedValue.setValue(0);
161
+      this.stopInterval();
162
+      this.setState(
163
+        {
164
+          heightOffset,
165
+          height,
166
+          width
167
+        },
168
+        () => {
169
+          if (enableAnimation) {
170
+            Animated.timing(this.opacityAnimatedValue, {
171
+              toValue: 1,
172
+              duration: animationDuration
173
+            }).start(() => {
174
+              handleSizeUpdated(height, width, onSizeUpdated);
175
+            });
176
+          } else {
177
+            handleSizeUpdated(height, width, onSizeUpdated);
178
+          }
179
+        }
180
+      );
181
+    }
182
+    const { onMessage } = this.props;
183
+    onMessage && onMessage(e);
186 184
   };
187 185
 
188 186
   onLoadingStart = event => {
@@ -203,8 +201,6 @@ export default class AutoHeightWebView extends PureComponent {
203 201
     onLoadEnd && onLoadEnd(event);
204 202
   };
205 203
 
206
-  getWebView = webView => (this.webView = webView);
207
-
208 204
   stopLoading() {
209 205
     UIManager.dispatchViewManagerCommand(
210 206
       findNodeHandle(this.webView),
@@ -214,23 +210,22 @@ export default class AutoHeightWebView extends PureComponent {
214 210
   }
215 211
 
216 212
   render() {
217
-      const { height, width, script, isChangingSource, heightOffset, widthOffset } = this.state;
218
-    const { scalesPageToFit, enableAnimation, source, customScript, style, enableBaseUrl } = this.props;
213
+    const { height, width, script, isChangingSource, heightOffset } = this.state;
214
+    const { scalesPageToFit, enableAnimation, source, customScript, style, enableBaseUrl, scrollEnabled } = this.props;
219 215
     let webViewSource = source;
220 216
     if (enableBaseUrl) {
221 217
       webViewSource = Object.assign({}, source, {
222 218
         baseUrl: 'file:///android_asset/web/'
223 219
       });
224 220
     }
225
-      
226 221
     return (
227 222
       <Animated.View
228 223
         style={[
229 224
           styles.container,
230 225
           {
231 226
             opacity: enableAnimation ? this.opacityAnimatedValue : 1,
232
-              height: height + heightOffset,
233
-              width: width + widthOffset
227
+            height: height + heightOffset,
228
+            width: width
234 229
           },
235 230
           style
236 231
         ]}
@@ -240,11 +235,13 @@ export default class AutoHeightWebView extends PureComponent {
240 235
             onLoadingStart={this.onLoadingStart}
241 236
             onLoadingFinish={this.onLoadingFinish}
242 237
             onLoadingError={this.onLoadingError}
243
-            ref={this.getWebView}
238
+            originWhitelist={['*']}
239
+            ref={this.webView}
244 240
             style={styles.webView}
245 241
             javaScriptEnabled={true}
246 242
             injectedJavaScript={script + customScript}
247 243
             scalesPageToFit={scalesPageToFit}
244
+            scrollEnabled={!!scrollEnabled}
248 245
             source={webViewSource}
249 246
             onMessage={this.onMessage}
250 247
             messagingEnabled={true}
@@ -261,7 +258,6 @@ const isBelowKitKat = Platform.Version < 19;
261 258
 
262 259
 const styles = StyleSheet.create({
263 260
   container: {
264
-    //width: screenWidth,
265 261
     backgroundColor: 'transparent'
266 262
   },
267 263
   webView: {
@@ -270,41 +266,42 @@ const styles = StyleSheet.create({
270 266
   }
271 267
 });
272 268
 
273
-const baseScript = isBelowKitKat
274
-  ? `
275
-    ; (function () {
276
-        var wrapper = document.createElement('div');
277
-        wrapper.id = 'wrapper';
278
-        while (document.body.firstChild instanceof Node) {
279
-            wrapper.appendChild(document.body.firstChild);
280
-        }
281
-        document.body.appendChild(wrapper);
282
-
283
-        AutoHeightWebView.onMessage = function (message) {
284
-            var rect = document.body.firstElementChild.getBoundingClientRect().toJSON();
285
-            var width = Math.round(rect.width);
286
-            var height = Math.round(rect.height);
287
-            AutoHeightWebView.send(JSON.stringify({ width, height }));
288
-        };
289
-        ${domMutationObserveScript}
290
-    } ());
291
-    `
292
-  : `
293
-    ; (function () {
294
-        var wrapper = document.createElement('div');
295
-        wrapper.id = 'wrapper';
296
-        while (document.body.firstChild instanceof Node) {
297
-            wrapper.appendChild(document.body.firstChild);
298
-        }
299
-        document.body.appendChild(wrapper);
300
-
301
-        document.addEventListener('message', function (e) {
302
-            var rect = document.body.firstElementChild.getBoundingClientRect().toJSON();
303
-            var width = Math.round(rect.width);
304
-            var height = Math.round(rect.height);
305
-            window.postMessage(JSON.stringify({ width, height }));
306
-        });
307
-        ${domMutationObserveScript}
308
-    } ());
309
-    `;
310
-
269
+const getBaseScript = isBelowKitKat
270
+  ? function() {
271
+      return `
272
+  ; (function () {
273
+    var wrapper = document.createElement('div');
274
+    wrapper.id = 'wrapper';
275
+    while (document.body.firstChild instanceof Node) {
276
+        wrapper.appendChild(document.body.firstChild);
277
+    }
278
+    document.body.appendChild(wrapper);
279
+    AutoHeightWebView.onMessage = function (message) {
280
+        var rect = document.body.firstElementChild.getBoundingClientRect().toJSON();
281
+        var width = Math.round(rect.width);
282
+        var height = Math.round(rect.height);
283
+        AutoHeightWebView.send(JSON.stringify({ width, height }));
284
+    };
285
+    ${domMutationObserveScript}
286
+} ());
287
+  `;
288
+    }
289
+  : function() {
290
+      return `
291
+  ; (function () {
292
+    var wrapper = document.createElement('div');
293
+    wrapper.id = 'wrapper';
294
+    while (document.body.firstChild instanceof Node) {
295
+        wrapper.appendChild(document.body.firstChild);
296
+    }
297
+    document.body.appendChild(wrapper);
298
+    document.addEventListener('message', function (e) {
299
+        var rect = document.body.firstElementChild.getBoundingClientRect().toJSON();
300
+        var width = Math.round(rect.width);
301
+        var height = Math.round(rect.height);
302
+        window.postMessage(JSON.stringify({ width, height }));
303
+    });
304
+    ${domMutationObserveScript}
305
+} ());
306
+  `;
307
+    };

+ 4
- 4
demo/android/app/build.gradle ファイルの表示

@@ -94,13 +94,13 @@ def enableSeparateBuildPerCPUArchitecture = false
94 94
 def enableProguardInReleaseBuilds = false
95 95
 
96 96
 android {
97
-    compileSdkVersion 23
98
-    buildToolsVersion "23.0.1"
97
+    compileSdkVersion 26
98
+    buildToolsVersion "27.0.3"
99 99
 
100 100
     defaultConfig {
101 101
         applicationId "com.demo"
102 102
         minSdkVersion 16
103
-        targetSdkVersion 22
103
+        targetSdkVersion 26
104 104
         versionCode 1
105 105
         versionName "1.0"
106 106
         ndk {
@@ -139,7 +139,7 @@ android {
139 139
 dependencies {
140 140
     compile project(':react-native-autoheight-webview')
141 141
     compile fileTree(dir: "libs", include: ["*.jar"])
142
-    compile "com.android.support:appcompat-v7:23.0.1"
142
+    compile "com.android.support:appcompat-v7:26.1.0"
143 143
     compile "com.facebook.react:react-native:+"  // From node_modules
144 144
 }
145 145
 

+ 9
- 1
demo/android/build.gradle ファイルの表示

@@ -3,6 +3,10 @@
3 3
 buildscript {
4 4
     repositories {
5 5
         jcenter()
6
+        maven {
7
+            url 'https://maven.google.com/'
8
+            name 'Google'
9
+        }
6 10
     }
7 11
     dependencies {
8 12
         classpath 'com.android.tools.build:gradle:2.2.3'
@@ -20,5 +24,9 @@ allprojects {
20 24
             // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
21 25
             url "$rootDir/../node_modules/react-native/android"
22 26
         }
27
+        maven {
28
+            url 'https://maven.google.com/'
29
+            name 'Google'
30
+        }
23 31
     }
24
-}
32
+}