Reputation: 8249
If I tap onto a textinput, I want to be able to tap somewhere else in order to dismiss the keyboard again (not the return key though). I haven't found the slightest piece of information concerning this in all the tutorials and blog posts that I read.
This basic example is still not working for me with react-native 0.4.2 in the Simulator. Couldn't try it on my iPhone yet.
<View style={styles.container}>
<Text style={styles.welcome}>
Welcome to React Native!
</Text>
<Text style={styles.instructions}>
To get started, edit index.ios.js
</Text>
<Text style={styles.instructions}>
Press Cmd+R to reload,{'\n'}
Cmd+D or shake for dev menu
</Text>
<TextInput
style={{height: 40, borderColor: 'gray', borderWidth: 1}}
onEndEditing={this.clearFocus}
/>
</View>
Upvotes: 724
Views: 473860
Reputation: 29
import {KeyboardAwareScrollView} from 'react-native-keyboard-aware-scroll-view';
use keyboardAwareScrollView as parent
Upvotes: 1
Reputation: 81
2023 answer:
You can add thereturnKeyType
prop to the TextInput to specify the text displayed on the return key of the keyboard. Setting it to "done" will display a "Done" button, which will dismiss the keyboard when pressed.
<TextInput
style={{height: 40, borderColor: 'gray', borderWidth: 1}}
onEndEditing={this.clearFocus}
returnKeyType="done"
/>
And it'll show the "done" button like this:
Upvotes: 5
Reputation: 49661
{/* KeyboardAvoidingView is to avoid the keyboard if the screen is smaller. it will shift the UI content up */}
{/* keyboardVerticalOffset tells where our view starts */}
{/* behaviour "padding" best works for ios, "height" best works for android */}
<KeyboardAvoidingView
// maybe you have a header and you want to start after header
keyboardVerticalOffset={yourViewHeaderHeight}
// "behavior" tells what property should change in case of changing our view
behavior={Platform.OS === "ios" ? "padding" : "height"}
style={{ flex: 1 }}
>
Upvotes: 0
Reputation: 91
Wrap the View
component that is the parent of the TextInput
in a Pressable
component and then pass Keyboard. dismiss
to the onPress
prop. So, if the user taps anywhere outside the TextInput
field, it will trigger Keyboard. dismiss
, resulting in the TextInput
field losing focus and the keyboard being hidden.
<Pressable onPress={Keyboard.dismiss}>
<View>
<TextInput
multiline={true}
onChangeText={onChangeText}
value={text}
placeholder={...}
/>
</View>
</Pressable>
Upvotes: 8
Reputation: 187
Using KeyBoard API from react-native does the trick.
import { Keyboard } from 'react-native'
// Hide the keyboard whenever you want using !
Keyboard.dismiss()
Upvotes: 17
Reputation: 2035
Use ScrollView
instead of View
with the attribute of keyboardShouldPersistTaps={"always"}
. It hides the keyboard when we click anywhere inside of the screen
<ScrollView keyboardShouldPersistTaps={"always"}>
<View style={styles.container}>
<Text style={styles.welcome}>
Welcome to React Native!
</Text>
<Text style={styles.instructions}>
To get started, edit index.ios.js
</Text>
<Text style={styles.instructions}>
Press Cmd+R to reload,{'\n'}
Cmd+D or shake for dev menu
</Text>
<TextInput
style={{height: 40, borderColor: 'gray', borderWidth: 1}}
onEndEditing={this.clearFocus}
/>
</View>
</ScrollView>
Upvotes: -1
Reputation: 6693
The onStartShouldSetResponder prop stops the touch event propagation towards the TouchableWithoutFeedback element.
<TouchableWithoutFeedback onPress={...}>
<View>
<ScrollView>
<View onStartShouldSetResponder={() => true}>
// Scrollable content
</View>
</ScrollView>
</View>
</TouchableWithoutFeedback>
Upvotes: 0
Reputation: 1252
The simplest way to do this
import {Keyboard} from 'react-native'
and then use the function Keyboard.dismiss()
That's all.
Here is a screenshot of my code so you can understand faster.
Now wrap the entire view with TouchableWithoutFeedback
and onPress function is keyboard.dismiss()
In this way if user tap on anywhere of the screen excluding textInput field, keyboard will be dismissed.
Upvotes: 25
Reputation: 163
We can use keyboard and tochablewithoutfeedback from react-native
const DismissKeyboard = ({ children }) => (
<TouchableWithoutFeedback
onPress={() => Keyboard.dismiss()}
>
{children}
</TouchableWithoutFeedback>
);
And use it in this way:
const App = () => (
<DismissKeyboard>
<View style={styles.container}>
<TextInput
style={styles.input}
placeholder="username"
keyboardType="numeric"
/>
<TextInput
style={styles.input}
placeholder="password"
/>
</View>
</DismissKeyboard>
);
I also explained here with source code.
Upvotes: 10
Reputation: 6774
This just got updated and documented! No more hidden tricks.
import { Keyboard } from 'react-native'
// Hide that keyboard!
Keyboard.dismiss()
Upvotes: 417
Reputation: 2195
import {Keyboard} from 'react-native';
use Keyboard.dismiss()
to hide your keyboard in any onClick or onPress event.
Upvotes: 1
Reputation: 2660
use this package react-native-keyboard-aware-scroll-view
use that component as your root component
since this package react-native-keyboard-aware-scroll-view
also have an scrollView you need to add this to it:
<KeyboardAwareScrollView keyboardShouldPersistTaps="handled">
<ScrollView keyboardShouldPersistTaps="handled"></ScrollView>
</KeyboardAwareScrollView>
Upvotes: 1
Reputation: 703
Wrap your whole component with:
import { TouchableWithoutFeedback, Keyboard } from 'react-native'
<TouchableWithoutFeedback onPress={() => Keyboard.dismiss()}>
...
</TouchableWithoutFeedback>
Worked for me
Upvotes: 10
Reputation: 4023
There are a few ways,
if you control of event like onPress
you can use:
import { Keyboard } from 'react-native'
onClickFunction = () => {
Keyboard.dismiss()
}
if you want to close the keyboard when the use scrolling:
<ScrollView keyboardDismissMode={'on-drag'}>
//content
</ScrollView>
More option is when the user clicks outside the keyboard:
<KeyboardAvoidingView behavior='padding' style={{ flex: 1}}>
//inputs and other content
</KeyboardAvoidingView>
Upvotes: 20
Reputation: 516
Here is my solution for Keyboard dismissing and scrolling to tapped TextInput (I am using ScrollView with keyboardDismissMode prop):
import React from 'react';
import {
Platform,
KeyboardAvoidingView,
ScrollView
} from 'react-native';
const DismissKeyboard = ({ children }) => {
const isAndroid = Platform.OS === 'android';
const behavior = isAndroid ? false : 'padding';
return (
<KeyboardAvoidingView
enabled
behavior={ behavior }
style={{ flex: 1}}
>
<ScrollView
keyboardShouldPersistTaps={'always'}
keyboardDismissMode={'on-drag'}
>
{ children }
</ScrollView>
</KeyboardAvoidingView>
);
};
export default DismissKeyboard;
usage:
render(){
return(
<DismissKeyboard>
<TextInput
style={{height: 40, borderColor: 'gray', borderWidth: 1}}
onChangeText={(text) => this.setState({text})}
value={this.state.text}
/>
</DismissKeyboard>
);
}
Upvotes: 1
Reputation: 104870
You can import keyboard
from react-native like below:
import { Keyboard } from 'react-native';
and in your code could be something like this:
render() {
return (
<TextInput
onSubmit={Keyboard.dismiss}
/>
);
}
static dismiss()
Dismisses the active keyboard and removes focus.
Upvotes: 40
Reputation: 883
Keyboard module is used to control keyboard events.
import { Keyboard } from 'react-native'
Add below code in render method.
render() {
return <TextInput onSubmitEditing={Keyboard.dismiss} />;
}
You can use -
Keyboard.dismiss()
static dismiss() Dismisses the active keyboard and removes focus as per react native documents.
Upvotes: 9
Reputation: 1196
Wrapping your components in a TouchableWithoutFeedback
can cause some weird scroll behavior and other issues. I prefer to wrap my topmost app in a View
with the onStartShouldSetResponder
property filled in. This will allow me to handle all unhandled touches and then dismiss the keyboard. Importantly, since the handler function returns false the touch event is propagated up like normal.
handleUnhandledTouches(){
Keyboard.dismiss
return false;
}
render(){
<View style={{ flex: 1 }} onStartShouldSetResponder={this.handleUnhandledTouches}>
<MyApp>
</View>
}
Upvotes: 28
Reputation: 442
First import Keyboard
import { Keyboard } from 'react-native'
Then inside your TextInput
you add Keyboard.dismiss
to the onSubmitEditing
prop. You should have something that looks like this:
render(){
return(
<View>
<TextInput
onSubmitEditing={Keyboard.dismiss}
/>
</View>
)
}
Upvotes: 6
Reputation: 3805
There are many ways you could handle this, the answers above don't include returnType
as it was not included in react-native that time.
1: You can solve it by wrapping your components inside ScrollView, by default ScrollView closes the keyboard if we press somewhere. But incase you want to use ScrollView but disable this effect. you can use pointerEvent prop to scrollView
pointerEvents = 'none'
.
2: If you want to close the keyboard on a button press, You can just use Keyboard
from react-native
import { Keyboard } from 'react-native'
and inside onPress of that button, you can use
Keyboard.dismiss()'.
3: You can also close the keyboard when you click the return key on the keyboard,
NOTE: if your keyboard type is numeric, you won't have a return key.
So, you can enable it by giving it a prop, returnKeyType to done
.
or you could use onSubmitEditing={Keyboard.dismiss}
,It gets called whenever we press the return key. And if you want to dismiss the keyboard when losing focus, you can use onBlur prop, onBlur = {Keyboard.dismiss}
Upvotes: 3
Reputation: 10952
The problem with keyboard not dismissing gets more severe if you have keyboardType='numeric'
, as there is no way to dismiss it.
Replacing View with ScrollView is not a correct solution, as if you have multiple textInput
s or button
s, tapping on them while the keyboard is up will only dismiss the keyboard.
Correct way is to encapsulate View with TouchableWithoutFeedback
and calling Keyboard.dismiss()
EDIT: You can now use ScrollView
with keyboardShouldPersistTaps='handled'
to only dismiss the keyboard when the tap is not handled by the children (ie. tapping on other textInputs or buttons)
If you have
<View style={{flex: 1}}>
<TextInput keyboardType='numeric'/>
</View>
Change it to
<ScrollView contentContainerStyle={{flexGrow: 1}}
keyboardShouldPersistTaps='handled'
>
<TextInput keyboardType='numeric'/>
</ScrollView>
or
import {Keyboard} from 'react-native'
<TouchableWithoutFeedback onPress={Keyboard.dismiss} accessible={false}>
<View style={{flex: 1}}>
<TextInput keyboardType='numeric'/>
</View>
</TouchableWithoutFeedback>
EDIT: You can also create a Higher Order Component to dismiss the keyboard.
import React from 'react';
import { TouchableWithoutFeedback, Keyboard, View } from 'react-native';
const DismissKeyboardHOC = (Comp) => {
return ({ children, ...props }) => (
<TouchableWithoutFeedback onPress={Keyboard.dismiss} accessible={false}>
<Comp {...props}>
{children}
</Comp>
</TouchableWithoutFeedback>
);
};
const DismissKeyboardView = DismissKeyboardHOC(View)
Simply use it like this
...
render() {
<DismissKeyboardView>
<TextInput keyboardType='numeric'/>
</DismissKeyboardView>
}
NOTE: the accessible={false}
is required to make the input form continue to be accessible through VoiceOver. Visually impaired people will thank you!
Upvotes: 917
Reputation: 47581
Keyboard.dismiss()
React Native exposed the static dismiss()
method on the Keyboard
, so the updated method is:
import { Keyboard } from 'react-native';
Keyboard.dismiss()
dismissKeyboard
Library.I had a very similar problem and felt like I was the only one that didn't get it.
If you have a ScrollView
, or anything that inherits from it like a ListView
, you can add a prop that will automatically dismiss the keyboard based on press or dragging events.
The prop is keyboardDismissMode
and can have a value of none
, interactive
or on-drag
. You can read more on that here.
If you have something other than a ScrollView
and you'd like any presses to dismiss the keyboard, you can use a simple TouchableWithoutFeedback
and have the onPress
use React Native's utility library dismissKeyboard
to dismiss the keyboard for you.
In your example, you could do something like this:
var DismissKeyboard = require('dismissKeyboard'); // Require React Native's utility library.
// Wrap your view with a TouchableWithoutFeedback component like so.
<View style={styles.container}>
<TouchableWithoutFeedback onPress={ () => { DismissKeyboard() } }>
<View>
<Text style={styles.welcome}>
Welcome to React Native!
</Text>
<Text style={styles.instructions}>
To get started, edit index.ios.js
</Text>
<Text style={styles.instructions}>
Press Cmd+R to reload,{'\n'}
Cmd+D or shake for dev menu
</Text>
<TextInput style={{height: 40, borderColor: 'gray', borderWidth: 1}} />
</View>
</TouchableWithoutFeedback>
</View>
Note: TouchableWithoutFeedback
can only have a single child so you need to wrap everything below it in a single View
as shown above.
Upvotes: 117
Reputation: 13976
const dismissKeyboard = require('dismissKeyboard');
dismissKeyboard(); //dismisses it
Approach No# 2;
Thanks to user @ricardo-stuven for pointing this out, there is another better way to dismiss the keyboard which you can see in the example in the react native docs.
Simple import Keyboard
and call it's method dismiss()
Upvotes: 14
Reputation: 2195
use this for custom dismissal
var dismissKeyboard = require('dismissKeyboard');
var TestView = React.createClass({
render: function(){
return (
<TouchableWithoutFeedback
onPress={dismissKeyboard}>
<View />
</TouchableWithoutFeedback>
)
}
})
Upvotes: 106
Reputation: 1217
I'm brand new to React, and ran into the exact same issue while making a demo app. If you use the onStartShouldSetResponder
prop (described here), you can grab touches on a plain old React.View
. Curious to hear more experienced React-ers' thoughts on this strategy / if there's a better one, but this is what worked for me:
containerTouched(event) {
this.refs.textInput.blur();
return false;
}
render() {
<View onStartShouldSetResponder={this.containerTouched.bind(this)}>
<TextInput ref='textInput' />
</View>
}
2 things to note here. First, as discussed here, there's not yet a way to end editing of all subviews, so we have to refer to the TextInput
directly to blur it. Second, the onStartShouldSetResponder
is intercepted by other touchable controls on top of it. So clicking on a TouchableHighlight
etc (including another TextInput
) within the container view will not trigger the event. However, clicking on an Image
within the container view will still dismiss the keyboard.
Upvotes: 39
Reputation: 35286
Use ScrollView
instead of View
and set the keyboardShouldPersistTaps
attribute to false.
<ScrollView style={styles.container} keyboardShouldPersistTaps={false}>
<TextInput
placeholder="Post Title"
onChange={(event) => this.updateTitle(event.nativeEvent.text)}
style={styles.default}/>
</ScrollView>
Upvotes: 35
Reputation: 11600
How about placing a touchable component around/beside the TextInput
?
var INPUTREF = 'MyTextInput';
class TestKb extends Component {
constructor(props) {
super(props);
}
render() {
return (
<View style={{ flex: 1, flexDirection: 'column', backgroundColor: 'blue' }}>
<View>
<TextInput ref={'MyTextInput'}
style={{
height: 40,
borderWidth: 1,
backgroundColor: 'grey'
}} ></TextInput>
</View>
<TouchableWithoutFeedback onPress={() => this.refs[INPUTREF].blur()}>
<View
style={{
flex: 1,
flexDirection: 'column',
backgroundColor: 'green'
}}
/>
</TouchableWithoutFeedback>
</View>
)
}
}
Upvotes: 10
Reputation: 231
If any one needs a working example of how to dismiss a multiline text input here ya go! Hope this helps some folks out there, the docs do not describe a way to dismiss a multiline input at all, at least there was no specific reference on how to do it. Still a noob to actually posting here on the stack, if anyone thinks this should be a reference to the actual post this snippet was written for let me know.
import React, { Component } from 'react'
import {
Keyboard,
TextInput,
TouchableOpacity,
View,
KeyboardAvoidingView,
} from 'react-native'
class App extends Component {
constructor(props) {
super(props)
this.state = {
behavior: 'position',
}
this._keyboardDismiss = this._keyboardDismiss.bind(this)
}
componentWillMount() {
this.keyboardDidHideListener = Keyboard.addListener('keyboardDidHide', this._keyboardDidHide);
}
componentWillUnmount() {
this.keyboardDidHideListener.remove()
}
_keyboardDidHide() {
Keyboard.dismiss()
}
render() {
return (
<KeyboardAvoidingView
style={{ flex: 1 }}
behavior={this.state.behavior}
>
<TouchableOpacity onPress={this._keyboardDidHide}>
<View>
<TextInput
style={{
color: '#000000',
paddingLeft: 15,
paddingTop: 10,
fontSize: 18,
}}
multiline={true}
textStyle={{ fontSize: '20', fontFamily: 'Montserrat-Medium' }}
placeholder="Share your Success..."
value={this.state.text}
underlineColorAndroid="transparent"
returnKeyType={'default'}
/>
</View>
</TouchableOpacity>
</KeyboardAvoidingView>
)
}
}
Upvotes: 19