react-native表格自适应

需求背景:react-native的ScrollView组件内嵌入WebView,纵向的FlatList切换item时切换WebView的url。
难点:解决WebView和外部ScrollView的滑动冲突

<ScrollView>
	<FlatList />
	<WebView />
</ScrollView>

在这里插入图片描述
方案一: WebView的高度、宽度固定,手势落在WebView内时滑动时阻止外部ScrollView的滑动事件,手势离开时恢复ScrollView的滑动事件。

<ScrollView scrollEnabled={this.state.scrollEnabled}>
	<WebView 
       source={{uri: currentUrl}}
          style={styles.webview}
          scalesPageToFit={false}
          onLoad={() => {this.setSafeState({load: true})}}
          onTouchStart={() => {this.setSafeState({scrollEnabled: false})}}
          onTouchMove={() => {this.setSafeState({scrollEnabled: false})}}
          onTouchEnd={() => {this.setSafeState({scrollEnabled: true})}}
     />
	...
</ScrollView>

问题:由于频繁的滑动手势,setState的异步效率过慢导致scrollEnabled并没有随着手势改变而立马改变,导致在WebView内部上下滑动时,整个页面(ScrollView)也会跟着滑动。
解决方案:react-native的直接操作setNativePropsAPI

setScrollEnabled = (bool) => {
	this._WebViewCom.setNativeProps({scrollEnabled: bool})
}

<ScrollView scrollEnabled={this.state.scrollEnabled}>
	<WebView 
       source={{uri: currentUrl}}
          style={styles.webview}
          scalesPageToFit={false}
          bounces={false}//webview 内容到达底部时是否进行回弹
          ref={component => {this._WebViewCom = component}}
          onLoad={() => {this.setSafeState({load: true})}}
          onTouchStart={this.setScrollEnabled.bind(this, false)}
          onTouchMove={this.setScrollEnabled.bind(this, false)}
          onTouchEnd={this.setScrollEnabled.bind(this, true)}
     />
	...
</ScrollView>

方案二:设置WebView的高度和表格的高度一样,这样也可以完美避开ScrollView和WebView的滑动冲突,WebView内表格还可以左右滑动。

1、使用postMessage实现native和webView的通信,webView告诉native表格的高度,naitve再设置webView的高度。

 // postMessage接收表格的高度,实现表格高度自适应
 onMessage = (e) => {
     const event = e.nativeEvent;
     const height = parseInt(event.data);
     this.setSafeState({height});
 }


<WebView 
	onMessage={this.onMessage}
    source={{uri: currentUrl}}
    style={[styles.webview, height > 0 && {height}]}
    onLoad={() => {this.setSafeState({load: true})}}
    javaScriptEnabled={true}
    onError={this.onError}
    injectedJavaScript={`
        // 页面自适用
        let metaTag=document.createElement('meta');
        metaTag.name = "viewport"
        metaTag.content = "width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"
        document.getElementsByTagName('head')[0].appendChild(metaTag);
        // 获取表格的高度
        let height = window.getComputedStyle(document.getElementsByTagName('table')[0]).height;
        let h = parseInt(height) + 44;
        window.ReactNativeWebView.postMessage(h);
    `}
/>

问题: WebView页面是load完成之后从执行injectedJavaScript的js代码,所以WebView是有一个固定的高度,等接收到postMessage传过来的height之后,将WebView的高度设成这个height。一开始比较快,但是切换WebView的url时,如果表格比较大会很慢。

解决方案:让后端在返回的url的h5的<head>里加上页面自适应的代码:

<meta name="viewport" content="height=device-height, initial-scale=1, maximum-scale=1.0, user-scalable=0" />

并且页面onload完之后返回h5表格的高度, (也是加在h5的<hea>下)

<script>
    window.onload=function(){
        let height = window.getComputedStyle(document.getElementsByTagName('table')[0]).height;
        let h = parseInt(height, 10);
        document.title = h;
    }
</script>

react-native这边使用onNavigationStateChange(当导航状态发生变化的时候调用),页面不再需要之前使用postMessage那样等页面onload完之后执行js才能拿到height。

// 接收表格的高度,实现表格高度自适,title的值为table的高度
onNavigationStateChange = (navState) => {
   if (navState.title) {
       const height = parseInt(navState.title, 10) || 0; // turn NaN to 0
       this.setSafeState({height: height})
   }
}

<WebView 
	source={{uri: currentUrl}}
    style={[styles.webview, height > 0 && {height}]}
    onLoad={() => {this.setSafeState({load: true})}}
    onError={this.onError}
    bounces={false}
    onNavigationStateChange={this.onNavigationStateChange}
/>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值