├── .gitignore ├── .DS_Store ├── img └── demo.gif ├── package.json ├── LICENSE ├── README.md └── KeyboardDodgingView.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .npm-debug.log 3 | -------------------------------------------------------------------------------- /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shaddeen/react-native-keyboard-dodging-view/HEAD/.DS_Store -------------------------------------------------------------------------------- /img/demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shaddeen/react-native-keyboard-dodging-view/HEAD/img/demo.gif -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-native-keyboard-dodging-view", 3 | "version": "1.0.0", 4 | "description": "A view that shifts up when the keyboard is presented", 5 | "main": "KeyboardDodgingView.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "https://github.com/shaddeen/react-native-keyboard-dodging-view.git" 12 | }, 13 | "keywords": [ 14 | "react-native", 15 | "keyboard", 16 | "view", 17 | "component" 18 | ], 19 | "author": "Shad Deen", 20 | "license": "MIT", 21 | "bugs": { 22 | "url": "https://github.com/ide/react-native-keyboard-dodging-view/issues" 23 | }, 24 | "homepage": "https://github.com/shaddeen/react-native-keyboard-dodging-view" 25 | } 26 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Shad 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # react-native-keyboard-dodging-view 2 | 3 | A react-native component for iOS that shifts the view up when the keyboard is presented. There are a few examples of this available including [KeyboardAvoidingView](https://facebook.github.io/react-native/releases/next/docs/keyboardavoidingview.html) but I've run into issues with this, particularly when using multiple fields. This solution aims to tackle this problem. 4 | 5 | ![demo](https://github.com/shaddeen/react-native-keyboard-dodging-view/blob/master/img/demo.gif) 6 | 7 | ##Setup 8 | 9 | `npm install --save react-native-keyboard-dodging-view` 10 | 11 | ##Props 12 | 13 | | Prop | Type | | 14 | |---|---|---| 15 | | `verticalOffset` | `number` | (Optional) Additional vertical offset | 16 | 17 | ##Usage 18 | 19 | Import: 20 | ``` 21 | import KeyboardDodgingView from 'KeyboardDodgingView` 22 | ``` 23 | Example: 24 | ``` 25 | class Example extends Component { 26 | render() { 27 | return ( 28 | 29 | 30 | this.refs.secondField.focus()} style={{height: 50, margin: 10, marginBottom: 0, backgroundColor: 'white'}} /> 31 | 32 | 33 | 34 | ); 35 | } 36 | } 37 | ``` 38 | 39 | ##Features 40 | - Dynamically calculates the height required to shift contents up 41 | - Accounts for changes in keyboard size 42 | - Handles multiple textfield selection 43 | 44 | ##Outstanding issues 45 | - Slight jump when switching text fields via the keyboard return key on iOS 8 46 | - Measurements are off when content is vertically aligned by a container view (with `justifyContent: 'center'`) 47 | -------------------------------------------------------------------------------- /KeyboardDodgingView.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @providesModule KeyboardDodgingView 3 | * https://github.com/shaddeen/react-native-keyboard-dodging-view 4 | * @flow 5 | */ 6 | 7 | import React from 'react'; 8 | 9 | import { 10 | View, 11 | Keyboard, 12 | LayoutAnimation, 13 | Platform 14 | } from 'react-native'; 15 | 16 | class KeyboardDodgingView extends React.Component { 17 | static propTypes = { 18 | ...View.propTypes, 19 | verticalOffset: React.PropTypes.number 20 | }; 21 | 22 | static defaultProps = { 23 | verticalOffset: 0 24 | }; 25 | 26 | constructor () { 27 | super(); 28 | 29 | this.state = { 30 | top: 0 31 | }; 32 | } 33 | 34 | componentWillMount () { 35 | if (Platform.OS == 'ios') { 36 | this._subscriptions = [ 37 | Keyboard.addListener('keyboardWillChangeFrame', (event) => this.onKeyboardChange(event)), 38 | Keyboard.addListener('keyboardWillShow', (event) => this.onKeyboardWillShow(event)), 39 | Keyboard.addListener('keyboardWillHide', (event) => this.onKeyboardWillHide(event)) 40 | ]; 41 | } 42 | } 43 | 44 | componentWillUnmount () { 45 | Platform.OS == 'ios' && this._subscriptions.forEach((subscription) => subscription.remove()); 46 | } 47 | 48 | onKeyboardWillShow (event) { 49 | this._keyboardVisible = true; 50 | this.onKeyboardChange(event); 51 | } 52 | 53 | onKeyboardWillHide (event) { 54 | this._keyboardVisible = false; 55 | this._keyboardHeight = 0; 56 | this.onKeyboardChange(event); 57 | } 58 | 59 | onKeyboardChange (event) { 60 | let top = 0; 61 | 62 | if (!event || !this._frame) { 63 | this.setState({top}); 64 | return; 65 | } 66 | 67 | const {duration, easing, startCoordinates, endCoordinates} = event; 68 | const viewHeight = this._frame.height; 69 | const viewTopOffset = this._frame.y; 70 | 71 | if (this._keyboardHeight === endCoordinates.height) { 72 | return; 73 | } 74 | 75 | if (this._keyboardHeight !== endCoordinates.height || startCoordinates.screenY > endCoordinates.screenY) { 76 | if (endCoordinates.screenY - viewHeight < viewTopOffset) { 77 | top = endCoordinates.screenY - viewTopOffset - viewHeight - this.props.verticalOffset; 78 | } 79 | } 80 | 81 | this.animateLayout(duration, easing); 82 | this.setState({top}); 83 | if (this._keyboardVisible) { 84 | this._keyboardHeight = endCoordinates.height; 85 | } 86 | } 87 | 88 | animateLayout (duration = 250, easing = 'keyboard') { 89 | LayoutAnimation.configureNext({ 90 | duration: duration, 91 | update: { 92 | duration: duration, 93 | type: LayoutAnimation.Types[easing] 94 | } 95 | }); 96 | } 97 | 98 | onLayout (event) { 99 | if (event && event.nativeEvent.layout !== this._frame) { 100 | this._frame = event.nativeEvent.layout; 101 | this.props.onLayout && this.props.onLayout(event); 102 | } 103 | } 104 | 105 | render () { 106 | const {style, ...props} = this.props; 107 | return ( 108 | this.onLayout(event)} /> 109 | ); 110 | } 111 | } 112 | 113 | module.exports = KeyboardDodgingView; 114 | --------------------------------------------------------------------------------