webview使用100%高度等没办法自动填满父容器,反而会由于一开始没有渲染高度只有0,因此后面都看不到webview。webview必须指定一个高度,没办法自适应高度。经过注入js,监听渲染后高度,而后回调设置真正的100%高度回来,作到自适应。html
添加高度statereact
state = {
height: 0
}
复制代码
自适应ios
<WebView
source={{html: `
<!DOCTYPE html>
<html>
<body>
${html}
</body>
<script>
window.onload = function() {
// 回调高度
document.title = document.body.clientHeight;
}
</script>
</body>
`}}
onNavigationStateChange={(event)=>{
if(event.title != undefined) {
console.log('event title', event.title);
// 设置高度
this.setState({
height: parseInt(event.title)
});
}}}
/>
复制代码
在react native开发中第一个最容易遇到的坑就是点击输入框,ios的键盘遮挡住了输入框,看不到输入的内容。而直接使用第三方的库解决这个问题的过程当中又遇到了新的问题,github上开发的库没法解决问题。因此就只能自行封装一个来解决键盘遮挡输入框的问题。git
源码连接KeyboardAvoidingView.tsxgithub
import React from 'react';
import {Animated, Dimensions, EmitterSubscription, Keyboard, Platform, TextInput, UIManager} from 'react-native';
import {NavigationEventSubscription, NavigationScreenProp} from 'react-navigation';
interface IState {
height: Animated.Value;
}
export interface KeyboardAvoidingViewProps {
navigation: NavigationScreenProp<any, any>;
onInputChange?: (onInput: boolean) => void;
// 固定键盘高度
fixedKeyboardHeight?: boolean;
// 固定上浮高度
fixedHeight?: number;
// 键盘加上高度
addHeight?: number;
}
export default class KeyboardAvoidingView extends React.Component<KeyboardAvoidingViewProps, IState> {
state = {
height: new Animated.Value(0),
onInput: false
}
private didFocus?: NavigationEventSubscription;
private willBlur?: NavigationEventSubscription;
private keyboardDidShowSub?: EmitterSubscription;
private keyboardDidHideSub?: EmitterSubscription;
componentDidMount() {
this.didFocus = this.props.navigation.addListener('didFocus', () => {
this.keyboardDidShowSub = Keyboard.addListener('keyboardDidShow', this.handleKeyboardDidShow);
this.keyboardDidHideSub = Keyboard.addListener('keyboardDidHide', this.handleKeyboardDidHide);
});
this.willBlur = this.props.navigation.addListener('willBlur', () => {
this.keyboardDidShowSub && this.keyboardDidShowSub.remove();
this.keyboardDidHideSub && this.keyboardDidHideSub.remove();
});
}
handleKeyboardDidShow = (event: any) => {
this.props.onInputChange && this.props.onInputChange(true);
if (Platform.OS != 'ios') return;
console.log('handleKeyboardDidShow');
const { height: windowHeight } = Dimensions.get('window');
const addHeight = this.props.addHeight || 0;
const keyboardHeight = event.endCoordinates.height + addHeight;
const currentlyFocusedField = TextInput.State.currentlyFocusedField();
console.log('currentlyFocusedField', currentlyFocusedField);
if (currentlyFocusedField == null) return;
if (this.props.fixedHeight != undefined) {
Animated.timing(
this.state.height,
{
toValue: -this.props.fixedHeight,
duration: 200,
useNativeDriver: true,
}
).start();
return;
}
if (this.props.fixedKeyboardHeight) {
console.log('keyboardHeight', keyboardHeight);
Animated.timing(
this.state.height,
{
toValue: -keyboardHeight,
duration: 200,
useNativeDriver: true,
}
).start();
return;
}
UIManager.measure(currentlyFocusedField, (originX, originY, width, height, pageX, pageY) => {
const fieldHeight = height;
const fieldTop = pageY;
const gap = (windowHeight - keyboardHeight) - (fieldTop + fieldHeight);
console.log('windowHeight', windowHeight, 'keyboardHeight', keyboardHeight, 'gap', gap, 'fieldTop', fieldTop, 'fieldHeight', fieldHeight);
if (gap >= 0) {
return;
}
Animated.timing(
this.state.height,
{
toValue: gap,
duration: 200,
useNativeDriver: true,
}
).start();
});
}
handleKeyboardDidHide = () => {
this.props.onInputChange && this.props.onInputChange(false);
if (Platform.OS != 'ios') return;
console.log('handleKeyboardDidHide');
Animated.timing(
this.state.height,
{
toValue: 0,
duration: 200,
useNativeDriver: true,
}
).start();
}
render() {
if (Platform.OS == 'ios') {
return (
<Animated.View style={{flex: 1, transform: [{translateY: this.state.height}]}}>
{this.props.children}
</Animated.View>
);
}
return this.props.children;
}
}
复制代码
须要注意的是KeyboardAvoidingView与react-navigation配合使用,在路由push后事件还在监听,因此须要移除,而后等路由从新回来到当前页面再从新监听。web
将组件包裹在视图最上层便可react-native
<KeyboardAvoidingView navigation={this.props.navigation}>
<View>
<TextInput />
...
</View>
</KeyboardAvoidingView>
复制代码