Saya telah melihat peretasan ini untuk aplikasi asli untuk menggulir jendela secara otomatis, tetapi bertanya-tanya cara terbaik untuk melakukannya di React Native ... Ketika sebuah <TextInput>
bidang mendapat fokus dan diposisikan rendah dalam tampilan, keyboard akan menutupi bidang teks.
Anda dapat melihat masalah ini dalam contoh tampilan UIExplorer TextInputExample.js
.
Apakah ada yang punya solusi bagus?
Jawaban:
Jawaban 2017
Ini
KeyboardAvoidingView
mungkin cara terbaik untuk pergi sekarang. Lihat dokumennya di sini . Ini sangat sederhana dibandingkan denganKeyboard
modul yang memberi pengembang lebih banyak kontrol untuk melakukan animasi. Spencer Carli mendemonstrasikan semua cara yang mungkin di blog medianya .2015 Jawaban
Cara yang benar untuk melakukannya
react-native
tidak memerlukan pustaka eksternal, memanfaatkan kode asli, dan menyertakan animasi.Pertama tentukan fungsi yang akan menangani
onFocus
acara untuk masing-masingTextInput
(atau komponen lain yang ingin Anda gulirkan):// 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); }
Kemudian, dalam fungsi render Anda:
render () { return ( <ScrollView ref='scrollView'> <TextInput ref='username' onFocus={this.inputFocused.bind(this, 'username')} </ScrollView> ) }
Ini menggunakan
RCTDeviceEventEmitter
untuk acara dan ukuran keyboard, mengukur posisi komponen menggunakanRCTUIManager.measureLayout
, dan menghitung gerakan gulir tepat yang diperlukan discrollResponderInputMeasureAndScrollToKeyboard
.Anda mungkin ingin bermain-main dengan
additionalOffset
parameter, agar sesuai dengan kebutuhan desain UI spesifik Anda.sumber
import {findNodeHandle} from 'react-native'
stackoverflow.com/questions/37626851/…Facebook open source
KeyboardAvoidingView
di react native 0.29 untuk mengatasi masalah ini. Dokumentasi dan contoh penggunaan dapat ditemukan di sini .sumber
DeviceEventEmitter.addListener('keyboardDidShow', this.keyboardDidShow.bind(this));
Kami menggabungkan beberapa bentuk kode react-native-keyboard-spacer dan kode dari @Sherlock untuk membuat komponen KeyboardHandler yang dapat digabungkan dengan setiap View dengan elemen TextInput. Bekerja seperti pesona! :-)
/** * 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;
sumber
Pertama, Anda perlu menginstal react-native-keyboardevents .
Kemudian kembali ke tanah javascript:
Anda perlu mengimpor react-native-keyboardevents.
var KeyboardEvents = require('react-native-keyboardevents'); var KeyboardEventEmitter = KeyboardEvents.Emitter;
Kemudian dalam tampilan Anda, tambahkan beberapa status untuk ruang keyboard dan perbarui dari mendengarkan acara keyboard.
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, }; },
Terakhir, tambahkan spacer ke fungsi render Anda di bawah semuanya sehingga ketika itu meningkatkan ukuran, itu akan meningkatkan barang Anda.
<View style={{height: this.state.keyboardSpace}}></View>
Dimungkinkan juga untuk menggunakan api animasi, tetapi demi kesederhanaan kita hanya menyesuaikan setelah animasi.
sumber
this.listView.getScrollResponder().scrollTo(rowID * rowHeight);
Ini dipanggil pada TextInput baris saat menerima peristiwa onFocus.react-native-keyboard-aware-scroll-view memecahkan masalah bagi saya. react-native-keyboard-aware-scroll-view di GitHub
sumber
Coba ini:
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>); }
...
Itu berhasil untuk saya. Tampilan pada dasarnya menyusut saat keyboard ditampilkan, dan tumbuh kembali saat disembunyikan.
sumber
Sekadar ingin menyebutkan, sekarang sudah ada
KeyboardAvoidingView
di RN. Cukup impor dan gunakan sebagai modul lain di RN.Berikut ini tautan ke komit di RN:
https://github.com/facebook/react-native/commit/8b78846a9501ef9c5ce9d1e18ee104bfae76af2e
Ini tersedia dari 0.29.0
Mereka juga menyertakan contoh di UIExplorer.
sumber
Mungkin terlambat, tetapi solusi terbaik adalah menggunakan pustaka asli, IQKeyboardManager
Cukup seret dan lepas direktori IQKeyboardManager dari proyek demo ke proyek iOS Anda. Itu dia. Anda juga dapat mengatur beberapa valus, seperti isToolbar diaktifkan, atau spasi antara input teks dan keyboard di file AppDelegate.m. Detail lebih lanjut tentang penyesuaian ada di tautan halaman GitHub yang telah saya tambahkan.
sumber
Saya menggunakan TextInput.onFocus dan ScrollView.scrollTo.
... <ScrollView ref="scrollView"> ... <TextInput onFocus={this.scrolldown}> ... scrolldown: function(){ this.refs.scrollView.scrollTo(width*2/3); },
sumber
@Fenny_fenny
Jika Anda tidak keberatan tidak menganimasikan ketinggian pada kecepatan yang sama persis dengan kemunculan keyboard, Anda dapat menggunakan LayoutAnimation, sehingga setidaknya ketinggian tidak melompat ke tempatnya. misalnya
import LayoutAnimation dari react-native dan tambahkan metode berikut ke komponen Anda.
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); },
Beberapa contoh animasi adalah (Saya menggunakan pegas di atas):
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, }, }, }, };
MEMPERBARUI:
Lihat jawaban @ sherlock di bawah ini, mulai react-native 0.11, pengubahan ukuran keyboard dapat diselesaikan menggunakan fungsionalitas bawaan.
sumber
Anda dapat menggabungkan beberapa metode menjadi sesuatu yang sedikit lebih sederhana.
Lampirkan pendengar onFocus pada masukan Anda
<TextInput ref="password" secureTextEntry={true} onFocus={this.scrolldown.bind(this,'password')} />
Metode gulir ke bawah kami terlihat seperti:
scrolldown(ref) { const self = this; this.refs[ref].measure((ox, oy, width, height, px, py) => { self.refs.scrollView.scrollTo({y: oy - 200}); }); }
Ini memberi tahu tampilan gulir kami (ingat untuk menambahkan referensi) untuk menggulir ke bawah ke posisi input terfokus kami - 200 (kira-kira seukuran keyboard)
componentWillMount() { this.keyboardDidHideListener = Keyboard.addListener( 'keyboardWillHide', this.keyboardDidHide.bind(this) ) } componentWillUnmount() { this.keyboardDidHideListener.remove() } keyboardDidHide(e) { this.refs.scrollView.scrollTo({y: 0}); }
Di sini kami mengatur ulang tampilan gulir kami kembali ke atas,
sumber
Saya menggunakan metode yang lebih sederhana, tetapi ini belum beranimasi. Saya memiliki status komponen yang disebut "bumpedUp" yang defaultnya adalah 0, tetapi disetel ke 1 saat textInput mendapatkan fokus, seperti ini:
Di teks sayaInput:
Saya juga memiliki gaya yang memberi wadah pembungkus semua yang ada di layar itu margin bawah dan margin atas negatif, seperti ini:
mythingscontainer: { flex: 1, justifyContent: "center", alignItems: "center", flexDirection: "column", }, bumpedcontainer: { marginBottom: 210, marginTop: -210, },
Dan kemudian pada wadah pembungkus, saya mengatur gaya seperti ini:
<View style={[styles.mythingscontainer, this.state.bumpedUp && styles.bumpedcontainer]}>
Jadi, saat status "bumpedUp" disetel ke 1, gaya bumpedcontainer berlaku dan memindahkan konten ke atas.
Agak hacky dan marginnya di-hardcode, tetapi berfungsi :)
sumber
Saya menggunakan jawaban brysgo untuk menaikkan bagian bawah scrollview saya. Kemudian saya menggunakan onScroll untuk memperbarui posisi scrollview saat ini. Saya kemudian menemukan ini React Native: Mendapatkan posisi elemen untuk mendapatkan posisi input teks. Saya kemudian melakukan beberapa matematika sederhana untuk mengetahui apakah input ada dalam tampilan saat ini. Lalu saya menggunakan scrollTo untuk memindahkan jumlah minimum ditambah margin. Cukup mulus. Berikut kode untuk bagian bergulir:
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 ); } ); }; },
sumber
Saya juga menemui pertanyaan ini. Akhirnya, saya menyelesaikannya dengan menentukan ketinggian setiap adegan, seperti:
<Navigator ... sceneStyle={{height: **}} />
Dan, saya juga menggunakan modul pihak ketiga https://github.com/jaysoo/react-native-extra-dimensions-android untuk mendapatkan ketinggian yang sebenarnya.
sumber