Просто хотел упомянуть, теперь в RN есть KeyboardAvoidingView
. Просто импортируйте его и используйте его как любой другой модуль в RN.
Вот ссылка на фиксацию на RN:
https://github.com/facebook/ response-native / commit / 8b78846a9501ef9c5ce9d1e18ee104bfae76af2e
Он доступен из 0.29.0
. Они также включили пример в UIExplorer.
Возможно, это поздно, но лучшим решением является использование родной библиотеки, IQKeyboardManager
Просто перетащите каталог IQKeyboardManager из демонстрационного проекта в проект iOS. Вот и все. Также вы можете настроить некоторый valus, включенный isToolbar, или пробел между текстовым вводом и клавиатурой в файле AppDelegate.m. Более подробная информация о настройке содержится в ссылке на страницу GitHub, которую я добавил.
response-native-keyboard-aware-scroll-view решила проблему для меня. реагировать-родной-клавиатурой-прокрутки-просмотр на GitHub
Сначала вам нужно установить response-native-keysevents .
Затем вернитесь в javascript land:
Вам нужно импортировать сообщения, реагирующие на реакцию на клавиатуре.
var KeyboardEvents = require('react-native-keyboardevents');
var KeyboardEventEmitter = KeyboardEvents.Emitter;
Затем, по вашему мнению, добавьте некоторое состояние для пространства клавиатуры и обновите его от прослушивания событий клавиатуры.
getInitialState: function() {
KeyboardEventEmitter.on(KeyboardEvents.KeyboardDidShowEvent, (frames) => {
this.setState({keyboardSpace: frames.end.height});
});
KeyboardEventEmitter.on(KeyboardEvents.KeyboardWillHideEvent, (frames) => {
this.setState({keyboardSpace: 0});
});
return {
keyboardSpace: 0,
};
},
Наконец, добавьте разделитель к вашей функции рендеринга под всем, чтобы при увеличении размера
<View style={{height: this.state.keyboardSpace}}></View>
Также возможно использовать анимацию api, но для простоты мы просто настраиваем после анимации.
Я использую ответ brysgo, чтобы поднять нижнюю часть моего scrollview. Затем я использую onScroll для обновления текущей позиции scrollview. Затем я нашел это React Native: получение позиции элемента , чтобы получить позицию textinput. Затем я делаю некоторые простые математические вычисления, если вход находится в текущем виде. Затем я использую scrollTo для перемещения минимальной суммы плюс маржа. Это довольно гладко. Вот код для части прокрутки:
focusOn: function(target) {
return () => {
var handle = React.findNodeHandle(this.refs[target]);
UIManager.measureLayoutRelativeToParent( handle,
(e) => {console.error(e)},
(x,y,w,h) => {
var offs = this.scrollPosition + 250;
var subHeaderHeight = (Sizes.width > 320) ? Sizes.height * 0.067 : Sizes.height * 0.077;
var headerHeight = Sizes.height / 9;
var largeSpace = (Sizes.height - (subHeaderHeight + headerHeight));
var shortSpace = largeSpace - this.keyboardOffset;
if(y+h >= this.scrollPosition + shortSpace) {
this.refs.sv.scrollTo(y+h - shortSpace + 20);
}
if(y < this.scrollPosition) this.refs.sv.scrollTo(this.scrollPosition - (this.scrollPosition-y) - 20 );
}
);
};
},
@Stephen
Если вы не возражаете против того, чтобы анимация высоты была точно такой же, как на клавиатуре, вы можете просто использовать LayoutAnimation, чтобы по крайней мере высота не переходила место. например,
import LayoutAnimation from response-native и добавьте следующие методы к вашему компоненту.
getInitialState: function() {
return {keyboardSpace: 0};
},
updateKeyboardSpace: function(frames) {
LayoutAnimation.configureNext(animations.layout.spring);
this.setState({keyboardSpace: frames.end.height});
},
resetKeyboardSpace: function() {
LayoutAnimation.configureNext(animations.layout.spring);
this.setState({keyboardSpace: 0});
},
componentDidMount: function() {
KeyboardEventEmitter.on(KeyboardEvents.KeyboardDidShowEvent, this.updateKeyboardSpace);
KeyboardEventEmitter.on(KeyboardEvents.KeyboardWillHideEvent, this.resetKeyboardSpace);
},
componentWillUnmount: function() {
KeyboardEventEmitter.off(KeyboardEvents.KeyboardDidShowEvent, this.updateKeyboardSpace);
KeyboardEventEmitter.off(KeyboardEvents.KeyboardWillHideEvent, this.resetKeyboardSpace);
},
Некоторые анимации примера (я использую первую пружину):
var animations = {
layout: {
spring: {
duration: 400,
create: {
duration: 300,
type: LayoutAnimation.Types.easeInEaseOut,
property: LayoutAnimation.Properties.opacity,
},
update: {
type: LayoutAnimation.Types.spring,
springDamping: 400,
},
},
easeInEaseOut: {
duration: 400,
create: {
type: LayoutAnimation.Types.easeInEaseOut,
property: LayoutAnimation.Properties.scaleXY,
},
update: {
type: LayoutAnimation.Types.easeInEaseOut,
},
},
},
};
UPDATE:
См. ниже ответ @ sherlock, так как с учетом реакции 0.11 изменение размера клавиатуры может быть разрешено с использованием встроенных функций.
Facebook open sourced KeyboardAvoidingView
в ответе native 0.29 для решения этой проблемы. Пример документации и использования можно найти здесь здесь .
Мы объединили некоторые из кода формы response-native-keyboard-spacer и код из @Sherlock для создания компонента KeyboardHandler, который можно обернуть вокруг любого элемента View with TextInput. Работает как шарм! : -)
/**
* Handle resizing enclosed View and scrolling to input
* Usage:
* <KeyboardHandler ref='kh' offset={50}>
* <View>
* ...
* <TextInput ref='username'
* onFocus={()=>this.refs.kh.inputFocused(this,'username')}/>
* ...
* </View>
* </KeyboardHandler>
*
* offset is optional and defaults to 34
* Any other specified props will be passed on to ScrollView
*/
'use strict';
var React=require('react-native');
var {
ScrollView,
View,
DeviceEventEmitter,
}=React;
var myprops={
offset:34,
}
var KeyboardHandler=React.createClass({
propTypes:{
offset: React.PropTypes.number,
},
getDefaultProps(){
return myprops;
},
getInitialState(){
DeviceEventEmitter.addListener('keyboardDidShow',(frames)=>{
if (!frames.endCoordinates) return;
this.setState({keyboardSpace: frames.endCoordinates.height});
});
DeviceEventEmitter.addListener('keyboardWillHide',(frames)=>{
this.setState({keyboardSpace:0});
});
this.scrollviewProps={
automaticallyAdjustContentInsets:true,
scrollEventThrottle:200,
};
// pass on any props we don't own to ScrollView
Object.keys(this.props).filter((n)=>{return n!='children'})
.forEach((e)=>{if(!myprops[e])this.scrollviewProps[e]=this.props[e]});
return {
keyboardSpace:0,
};
},
render(){
return (
<ScrollView ref='scrollView' {...this.scrollviewProps}>
{this.props.children}
<View style={{height:this.state.keyboardSpace}}></View>
</ScrollView>
);
},
inputFocused(_this,refName){
setTimeout(()=>{
let scrollResponder=this.refs.scrollView.getScrollResponder();
scrollResponder.scrollResponderScrollNativeHandleToKeyboard(
React.findNodeHandle(_this.refs[refName]),
this.props.offset, //additionalOffset
true
);
}, 50);
}
}) // KeyboardHandler
module.exports=KeyboardHandler;
2017 Ответ
Вероятно, KeyboardAvoidingView
- лучший способ. Ознакомьтесь с документами здесь . Это действительно просто по сравнению с модулем Keyboard
, который дает разработчику больше возможностей для анимации. Спенсер Карли продемонстрировал все возможные способы в своем среднем блоге .
2015 Отвечать
Правильный способ сделать это в react-native
не требует внешних библиотек, использует собственный код и включает анимацию.
Сначала определите функцию, которая будет обрабатывать событие onFocus
для каждого TextInput
(или любого другого компонента, который вы хотели бы прокрутить):
// Scroll a component into view. Just pass the component ref string.
inputFocused (refName) {
setTimeout(() => {
let scrollResponder = this.refs.scrollView.getScrollResponder();
scrollResponder.scrollResponderScrollNativeHandleToKeyboard(
React.findNodeHandle(this.refs[refName]),
110, //additionalOffset
true
);
}, 50);
}
Затем в вашей функции рендеринга:
render () {
return (
<ScrollView ref='scrollView'>
<TextInput ref='username'
onFocus={this.inputFocused.bind(this, 'username')}
</ScrollView>
)
}
Это использует RCTDeviceEventEmitter
для событий и размеров клавиатуры, измеряет положение компонента с помощью RCTUIManager.measureLayout
и вычисляет точное перемещение прокрутки, требуемое в scrollResponderInputMeasureAndScrollToKeyboard
.
Вы можете захотеть поиграть с параметром additionalOffset
, чтобы соответствовать потребностям вашего конкретного дизайна пользовательского интерфейса.
Попробуйте следующее:
import React, {
DeviceEventEmitter,
Dimensions
} from 'react-native';
...
getInitialState: function() {
return {
visibleHeight: Dimensions.get('window').height
}
},
...
componentDidMount: function() {
let self = this;
DeviceEventEmitter.addListener('keyboardWillShow', function(e: Event) {
self.keyboardWillShow(e);
});
DeviceEventEmitter.addListener('keyboardWillHide', function(e: Event) {
self.keyboardWillHide(e);
});
}
...
keyboardWillShow (e) {
let newSize = Dimensions.get('window').height - e.endCoordinates.height;
this.setState({visibleHeight: newSize});
},
keyboardWillHide (e) {
this.setState({visibleHeight: Dimensions.get('window').height});
},
...
render: function() {
return (<View style={{height: this.state.visibleHeight}}>your view code here...</View>);
}
...
Это сработало для меня. Вид в основном сжимается, когда клавиатура отображается, и растет снова, когда она скрыта.
Я также встречаю этот вопрос. Наконец, я разрешаю его, определяя высоту каждой сцены, например:
<Navigator
...
sceneStyle={{height: **}}
/>
И также я использую сторонний модуль https: // github.com/jaysoo/react-native-extra-dimensions-android, чтобы получить реальную высоту.
Вы можете объединить несколько методов в нечто более простое.
Приложить прослушиватель onFocus на ваших входах
<TextInput ref="password" secureTextEntry={true}
onFocus={this.scrolldown.bind(this,'password')}
/>
Наш метод прокрутки вниз выглядит примерно так:
scrolldown(ref) {
const self = this;
this.refs[ref].measure((ox, oy, width, height, px, py) => {
self.refs.scrollView.scrollTo({y: oy - 200});
});
}
Это говорит нашему прокрутку (не забудьте добавить ссылку), чтобы прокрутить вниз до позиции нашего сфокусированного ввода - 200 (это примерно размер клавиатуры)
componentWillMount() {
this.keyboardDidHideListener = Keyboard.addListener(
'keyboardWillHide',
this.keyboardDidHide.bind(this)
)
}
componentWillUnmount() {
this.keyboardDidHideListener.remove()
}
keyboardDidHide(e) {
this.refs.scrollView.scrollTo({y: 0});
}
Здесь мы переустановили наш вид прокрутки вверх,
Я использовал TextInput.onFocus и ScrollView.scrollTo.
...
<ScrollView ref="scrollView">
...
<TextInput onFocus={this.scrolldown}>
...
scrolldown: function(){
this.refs.scrollView.scrollTo(width*2/3);
},
Я использую более простой метод, но он еще не анимирован. У меня есть состояние компонента, называемое «bumpedUp», которое по умолчанию равно 0, но устанавливается в 1, когда textInput получает фокус, например:
В моем тексте Вход:
onFocus={() => this.setState({bumpedUp: 1})}
onEndEditing={() => this.setState({bumpedUp: 0})}
У меня также есть стиль, который придает контейнеру для упаковки всего на этом экране нижнее поле и отрицательное верхнее поле, например:
mythingscontainer: {
flex: 1,
justifyContent: "center",
alignItems: "center",
flexDirection: "column",
},
bumpedcontainer: {
marginBottom: 210,
marginTop: -210,
},
И затем на контейнере для упаковки я устанавливаю такие стили:
<View style={[styles.mythingscontainer, this.state.bumpedUp && styles.bumpedcontainer]}>
Итак, когда состояние «bumpedUp» установлено в 1, стиль bumpedcontainer запускает и перемещает содержимое вверх.
Kinda hacky и поля жестко закодированы, но он работает:)