React Native done button above keyboard - react-native

I want to add a "Done" button above the keyboard, that will hide the keyboard when clicked.
Here's an image demonstrating the desired button:
Is there any existing method or library for that? (I already found this library but it doesn't work).

For numeric and number-pad :
and seems that you don't need any library
returnKeyType='done' works with "number-pad" and "numeric" on v0.47.1
for normal keyboard you may look at this :
https://github.com/ardaogulcan/react-native-keyboard-accessory
and
https://github.com/douglasjunior/react-native-keyboard-manager
Github thread you need to take a look at :
https://github.com/facebook/react-native/issues/1190
and
https://github.com/facebook/react-native/issues/641
Hope it helps

You can use React-native's KeyboardAvoidingView Component as
<KeyboardAvoidingView keyboardVerticalOffset={50}>
//View you want to be moved up when keyboard shows.
</KeyboardAvoidingView>
keyboardVerticalOffset={50}
is the margin between the keyboard and the view, which will be the height of view or button you want. I hope that helps.
Edit: the best and most customizable way I think to do this, is listening to Keyboard events and changing the absolute position of the component you want above the keyboard, according to it.
import {..,Keyboard} from "react-native";
componentDidMount () {
this.keyboardDidShowListener = Keyboard.addListener('keyboardDidShow',(event)=>this.keyboardDidShow(event) );
this.keyboardDidHideListener = Keyboard.addListener('keyboardDidHide',(event)=>this.keyboardDidHide(event) );
}
keyboardDidShow = (event) => {
// console.log("keyboard show",event)
this.setState({keyboardShow:true,keyboardHeight:event.endCoordinates.height}) //<<You got the keyboard height
}
keyboardDidHide = (event) => {
// console.log("keyboard hide",event)
this.setState({keyboardShow:false,keyboardHeight:0})
}
componentWillUnmount () {
this.keyboardDidShowListener.remove();
this.keyboardDidHideListener.remove();
}
now, to show it above the keyboard you can give style to your button component like this
style={{position:"absolute",bottom:this.state.keyboardHeight+20,right:0}}
and if you want to hide it (Done button) just condition the JSX with the keyboardShow state.

I am sharing my style of handling this case :
Code :
import React from 'react'
import { StyleSheet, Platform, View, Text, KeyboardAvoidingView, Keyboard } from 'react-native';
import { TextInput } from 'react-native-gesture-handler';
export default class StripAboveKeyboard extends React.Component {
constructor(props) {
super(props)
this.state = { keyboardHeight: 0 }
}
componentDidMount() {
this.keyboardDidShowListener = Keyboard.addListener('keyboardDidShow', (event) => this.keyboardDidShow(event));
this.keyboardDidHideListener = Keyboard.addListener('keyboardDidHide', (event) => this.keyboardDidHide(event));
}
keyboardDidShow = (event) => this.setState({ keyboardShow: true, keyboardHeight: event.endCoordinates.height > 100 ? (Platform.OS == 'ios' ? event.endCoordinates.height : 0) : 0 })
keyboardDidHide = (event) => this.setState({ keyboardShow: false, keyboardHeight: 0 })
componentWillUnmount() {
this.keyboardDidShowListener.remove();
this.keyboardDidHideListener.remove();
}
render() {
marginFromBottom = (this.state.keyboardHeight == 0) ? 0 : this.state.keyboardHeight
return (
<KeyboardAvoidingView style={{ flex: 1 }}>
<View style={style.parent}>
<View style={style.upper}>
<TextInput style={style.textInput}>User Name</TextInput>
</View>
<View style={{ ...style.bottomParent, marginBottom: marginFromBottom }}>
<Text style={style.bottom}>Press me</Text>
</View>
</View>
</KeyboardAvoidingView>)
}
}
const style = StyleSheet.create({
parent: {
flex: 1,
padding: 10,
backgroundColor: 'pink',
},
upper: {
paddingTop: 44,
backgroundColor: 'green',
padding: 10,
flex: 1,
marginBottom: 10,
},
textInput: {
height: 40, borderColor: 'gray', borderWidth: 1
},
bottomParent: {
justifyContent: "center",
alignItems: "center",
backgroundColor: 'red',
width: '100%',
height: 40,
},
bottom: {
textAlignVertical: "center", textAlign: "center",
}
})
Screenshots :
ANDROID & IOS

That is not a library or anything special. That is just a view that moves up with the keyboard.
Read this article - https://medium.freecodecamp.org/how-to-make-your-react-native-app-respond-gracefully-when-the-keyboard-pops-up-7442c1535580#.gd37tn1wx
It shows you different ways to make elements respect the keyboard.

Done button will not work for multiples line TextInput. To close keyboard you have to use
KeyboardAvoidingView
that will helpful to close it by touching outside of softkeyboard

Related

Hide the bottom image view when showing keyboard react-native

How I can hide this picture...
Thank you for any help!
You can use Keyboard in ReactNative to listen for changes of keyboard and hide your image when the keyboard is visible.
check below sample code
import * as React from "react";
import { View, Keyboard, TextInput, Image } from "react-native";
export default class App extends React.Component {
state = {
isKeyboadVisible: false,
text: ""
};
componentDidMount() {
this.keyboardDidShowListener = Keyboard.addListener(
"keyboardDidShow",
this._keyboardDidShow
);
this.keyboardDidHideListener = Keyboard.addListener(
"keyboardDidHide",
this._keyboardDidHide
);
}
componentWillUnmount() {
this.keyboardDidShowListener.remove();
this.keyboardDidHideListener.remove();
}
_keyboardDidShow = () => {
this.setState({
isKeyboadVisible: true
});
};
_keyboardDidHide = () => {
this.setState({
isKeyboadVisible: false
});
};
render() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<TextInput
style={{
height: 40,
width: "80%",
borderColor: "red",
borderWidth: 1,
marginBottom: 10
}}
onChangeText={text => this.setState({ text })}
value={this.state.text}
/>
{!this.state.isKeyboadVisible && (
<Image
style={{ width: 100, height: 100 }}
source={{ uri: "https://reactnative.dev/img/tiny_logo.png" }}
/>
)}
</View>
);
}
}
Change the above code according to your requirements.
Hope this helps you. Feel free for doubts.
You need to using ScrollView to wrapper your view. Therefore, when you click to input component, keyboard will overlap your picture.
https://reactnative.dev/docs/using-a-scrollview#__docusaurus
Another solution is try to using KeyboardAvoidingView
https://reactnative.dev/docs/keyboardavoidingview

how to expand a component on click to full screen width and height with animation in reactnative

I have tried to implement the component expand to full screen in react native by using Layout animation in react-native but it was not good to look. Can any one help me in getting it?
changeLayout = () => {
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
this.setState({ expanded: !this.state.expanded });
};
I expect to expand the component on click to full screen and again collapse it on click.
Set the initial value you want through the animation, obtain the screen width and height, and create a click function to execute.
This is an example that I made. Click this link if you want to run it yourself.
import React from 'react';
import { Animated, Text, View,Dimensions,Button } from 'react-native';
const screenwidth = Dimensions.get('screen').width
const screenheight = Dimensions.get('screen').height
class FadeInView extends React.Component {
state = {
fadeAnim: new Animated.Value(50),
fadeAnim2: new Animated.Value(50),
}
componentDidMount() {
}
animatebutton() {
Animated.timing( // Animate over time
this.state.fadeAnim, // The animated value to drive
{
toValue: screenheight,
duration: 10000, // Make it take a while
}
).start();
Animated.timing( // Animate over time
this.state.fadeAnim2, // The animated value to drive
{
toValue: screenwidth,
duration: 10000, // Make it take a while
}
).start(); // Starts the animation
}
render() {
let { fadeAnim,fadeAnim2 } = this.state;
return (
<Animated.View // Special animatable View
style={{
...this.props.style,
height: fadeAnim,
width : fadeAnim2
}}
>
{this.props.children}
</Animated.View>
);
}
}
// You can then use your `FadeInView` in place of a `View` in your components:
export default class App extends React.Component {
constructor(props){
super(props);
this.state={
}
}
animatebutton(){
this.fade.animatebutton();
}
render() {
return (
<View style={{flex: 1, alignItems: 'center', justifyContent: 'center'}} >
<FadeInView style={{backgroundColor: 'powderblue'}} ref={ani => this.fade = ani}>
<Text style={{fontSize: 28, textAlign: 'center', margin: 10}}>Fading in</Text>
</FadeInView>
<Button title="go animate" onPress={() => this.animatebutton()}/>
</View>
)
}
}
OR
You can use LayoutAnimation that you want to use. Look at my example.
import React, {Component} from "react";
import {
AppRegistry,
StyleSheet,
Text,
View,
TouchableOpacity,
LayoutAnimation,
} from 'react-native';
class App extends Component {
constructor() {
super();
this.state = {
check: false,
}
}
onPresscheck() {
// Uncomment to animate the next state change.
LayoutAnimation.configureNext(LayoutAnimation.Presets.spring);
// Or use a Custom Layout Animation
// LayoutAnimation.configureNext(CustomLayoutAnimation);
this.setState({ check : !this.state.check});
}
render() {
var middleStyle = this.state.check === false ? {width: 20,height:20} : {width: "100%",height:"100%"};
return (
<View style={styles.container}>
<TouchableOpacity style={styles.button} onPress={() => this.onPresscheck()}>
<Text>pressbutton</Text>
</TouchableOpacity>
<View style={[middleStyle, {backgroundColor: 'seagreen'}]}/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
button: {
width:"100%",
height: 60,
backgroundColor: 'blue',
alignItems: 'center',
justifyContent: 'center',
margin: 8,
},
});
export default App;
Please refer to this blog :
https://dev-yakuza.github.io/en/react-native/react-native-animatable/
Also, try using this library. Use any animation type you want and render them.
Happy coding :)

react native spinner doesn't display on bottom

So I got this piece of code, and I want to display the Spinner on the bottom of the screen, just right after the FlatList, but when the function displaySpinner is called nothing displays after the flatlist. I've tried many things like putting trying to display the Spinner on the top of the view and then give it a Top but it's not what I'm looking for.
By the way I'm new in the programming world and more on React Native so I hope everything makes sense to understand my problem
import React, { Component } from 'react';
import { FlatList, StyleSheet, View, Text, Image } from 'react-native';
import axios from 'axios';
import moment from 'moment';
import Card from './Card';
import CardSection from './CardSection';
import Spinner from './Spinner';
class ArticleList extends Component {
state = { articles: [],
refreshing: false,
isLoading: false,
};
componentWillMount() {
this.loadArticles();
}
currentOffset = 0;
reloadContent() {
this.setState({
isLoading: true
});
this.currentOffset += 20;
console.log(this.currentOffset);
this.loadArticles();
}
loadArticles = () => {
const { articles } = this.state;
console.log(this.currentOffset);
axios.get(`https://sportsoftheday.com/wp-json/wp/v2/posts?per_page=20&offset=${this.currentOffset}`)
.then(res =>
this.setState({
articles: this.currentOffset === 0 ? res.data : [...articles, ...res.data],
isLoading: false,
}))
.catch(err => {
console.error(err);
});
};
displaySpinner() {
if (this.state.isLoading === true) {
return <Spinner size='large' />;
}
}
//Apply removeClippedSubviews for eliminating useless data on the screen
render() {
const { articles } = this.state;
this.date = this.date;
this.fimg_url = this.fimg_url;
return (
<View>
<FlatList
data={articles}
renderItem={({ item }) => (
<Card>
<CardSection>
<View style={styles.thumbnailContainerStyle}>
<Image
style={styles.thumbnailStyle}
source={{
uri: item.fimg_url,
cache: 'only-if-cached'
}}
/>
</View>
<View style={styles.headerContentStyle}>
<Text style={{ color: '#B2B2B2' }}>
{moment(item.date).format('dddd, Do MMMM YYYY')}</Text>
<Text
numberOfLines={3}
style={styles.headerTextStyle}
>
{item.title.rendered}
</Text>
</View>
</CardSection>
</Card>
)}
keyExtractor={i => i.id}
onEndReached={this.reloadContent.bind(this)}
onEndReachedThreshold={0.1}
/>
{this.displaySpinner()}
</View>
);
}
}
const styles = StyleSheet.create({
headerContentStyle: {
flexDirection: 'column',
justifyContent: 'space-around',
flex: 1
},
headerTextStyle: {
textAlign: 'justify',
fontSize: 18,
color: 'black',
marginRight: 15
},
thumbnailStyle: {
height: 70,
width: 70
},
thumbnailContainerStyle: {
justifyContent: 'center',
alignItems: 'center',
marginLeft: 10,
marginRight: 10
},
imageStyle: {
height: 300,
flex: 1,
width: null
},
});
export default ArticleList;
First things first, you should always avoid rendering a view/component directly in the renderItem = { } prop of your FlatList. Always send a function that is bounded to your current context that returns a component renderItem = {this._renderItem.bind(this)} or renderItem = {() => renderItem()}. This is not an issue but a usual practice that keeps the code clean and professional. Just a suggestion since you mentioned you're new to RN.
Coming to your question, the spinner shall show up once you wrap your Spinner inside a View component. You can do this either by wrapping your function call <View> {this.displaySpinner()} </View> or return a component that is already wrapped in a View <View> <Spinner/> </View>.
To make this even more effective, wrap everything including your flatlist but excluding your Header if you have one (Obviously) inside a View and give it a style of flex flex: 1 with a direction of column 'flexDirection: 'column'. Now you can justify your content with justifyContent: 'space-around' or 'space-between' whichever works for you.
Final point I'd like to make is again a suggestion. I've been working on RN for a while now but I still find designing the UI one of the most tedious tasks. Hot Reloading helps but not much. To track your UI changes on the screen, you can give the style borderColor: 'red', borderWidth: 1 to your views. This will help you a lot. It sure helps me.
I hope this helps.
Best of luck
Wrap that spinner in a view like View style = {{ position: "absolute", bottom: 0, width: '100%'}}
{this.displaySpinner()}
Close View

How to open keyboard automatically in React Native when component mounts?

My page has only a single TextInput, and I have passed in the autoFocus prop: autoFocus: true.
<TextInput
style={styles.textInput}
placeholder="Quiz Deck Title"
autoFocus={true}
value={this.state.title}
onChangeText={(title) => this.controlledTextInput(title)}
/>
What I am trying to avoid is requiring the user to "click" in the TextInput box before the keyboard pops up.
But I would also like to have the soft keyboard also open automatically (if the device does not have a hardware keyboard).
Is there way to make this happen in react native? I am developing for both ios and android.
If it matters, my page is navigated to via TabNavigator.
I mention this because a comment to another similar SO question (see below) suggests they had a similar issue when they arrived at their page using StackNavigator.
Note on Similar SO questions:
How to open keyboard automatically in React Native?
: does not provide a solution, and comments by others suggest the same results as myself: input is focused, but keyboard does not automatically open.
Close/hide the Android Soft Keyboard
and Android: show soft keyboard automatically when focus is on an EditText
: are using native android code (java), not react native code (javascript).
Note: I am developing using the android emulator Nexus 6P with android 23 (as recommended), and ios simulator with iPhone 6s, as I do not have physical devices.
Edit: Adding Requested Code
NewDeck.js (the view I want the keyboard to auto pop up on):
import React from 'react';
import { connect } from 'react-redux';
import { View, Text, TouchableOpacity,
TextInput, KeyboardAvoidingView,
StyleSheet, Platform,
} from 'react-native';
import StyledButton from '../components/StyledButton';
import { saveDeck } from '../store/decks/actionCreators';
import { getDeckList } from '../store/decks/selectors';
import { fetchDecks } from '../utils/api';
import { saveDeckTitle } from '../utils/api';
} from '../utils/colors';
import { titleCase, stripInvalidChars, makeStringUnique }
from '../utils/helpers';
import { white, gray, primaryColor, primaryColorDark, primaryColorLight,
class NewDeck extends React.Component {
state = {
title: '',
canSubmit: false,
}
componentDidMount () {
this.textInputRef.focus()
}
controlledTextInput(title){
title = titleCase(stripInvalidChars(title));
const canSubmit = this.isValidInput(title);
this.setState({ title, canSubmit });
}
isValidInput(text){
return text.trim() !== '';
}
onBlur(){
title = this.state.title.trim();
const unique = makeStringUnique(title, this.props.existingTitles);
this.setState({ title: unique });
}
onSubmit(){
let title = this.state.title.trim();
title = makeStringUnique(title, this.props.existingTitles)
saveDeckTitle(title)
this.props.navigation.navigate('Home');
}
render() {
return (
<View style={styles.container}>
<View style={[styles.cardContainer, {flex: 1}]}>
<Text style={styles.instructionsText}
>
Title for your New Quiz Deck
</Text>
<KeyboardAvoidingView {...keyboardAvoidingViewProps}>
<TextInput
style={styles.textInput}
placeholder="Quiz Deck Title"
value={this.state.title}
onChangeText={(title) => this.controlledTextInput(title)}
/* autoFocus={true} */
ref={ref => this.textInputRef = ref}
/>
</KeyboardAvoidingView>
</View>
<KeyboardAvoidingView
{...keyboardAvoidingViewProps}
style={[styles.buttonsContainer, styles.buttonContainer]}
>
<StyledButton
style={[styles.item, style={flex: 2}]}
onPress={() => this.onSubmit()}
disabled={!this.state.canSubmit}
>
<Text>
Submit
</Text>
</StyledButton>
</KeyboardAvoidingView>
</View>
);
}
}
const keyboardAvoidingViewProps = {
behavior: 'padding',
};
// ...styles definition here, - I posted it in a later code block, to minimize
// clutter, in the event that it is irrelevant to this issue
function mapStoreToProps(store){
const decks = getDeckList(store) || null;
// ensure titles are unique (better UX than if just make id unique)
const existingTitles = decks && decks.map(deck => {
return deck.title
}) || [];
return {
existingTitles,
}
}
export default connect(mapStoreToProps)(NewDeck);
TabNavigator and StackNavigator code (in App.js):
// ... the TabNavigator I'm using:
import { TabNavigator, StackNavigator } from 'react-navigation';
//... the class's render method, uses StackNavigator (as MainNavigation)
render(){
return (
<Provider store={createStore(rootReducer)}>
<View style={{flex:1}}>
<AppStatusBar
backgroundColor={primaryColor}
barStyle="light-content"
/>
<MainNavigation />
</View>
</Provider>
);
}
}
// ...
const Tabs = TabNavigator(
{
DeckList: {
screen: DeckList,
navigationOptions: {
tabBarLabel: 'Quiz Decks',
tabBarIcon: ({ tintColor }) => // icons only show in ios
<Ionicons name='ios-bookmarks' size={30} color={tintColor} />
},
},
NewDeck: {
screen: NewDeck,
navigationOptions: {
tabBarLabel: 'Create New Deck',
tabBarIcon: ({ tintColor }) => // icons only show in ios
<FontAwesome name='plus-square' size={30} color={tintColor} />
},
},
},
{
navigationOptions: {
// do-not-display page headers for Tab Navigation
header: null
},
tabBarOptions: {
// ios icon and text color; android text color
activeTintColor: Platform.OS === 'ios' ? primaryColor : white,
pressColor: white,
indicatorStyle: {
backgroundColor: primaryColorDark,
height: 3,
},
style: {
height: 56,
backgroundColor: Platform.OS === 'ios' ? white : primaryColor,
shadowColor: 'rgba(0, 0, 0, 0.24)',
shadowOffset: {
width: 0,
height: 3
},
shadowRadius: 6,
shadowOpacity: 1
}
}
}
);
//... StackNavigator uses TabNavigator (as Tabs)
const stackScreenNavigationOptions = {
headerTintColor: white,
headerStyle: {
backgroundColor: primaryColor,
}
};
const MainNavigation = StackNavigator(
// RouteConfigs: This is analogous to defining Routes in a web app
{
Home: {
screen: Tabs, // Which also loads the first Tab (DeckList)
},
Deck: {
screen: Deck,
navigationOptions: stackScreenNavigationOptions,
},
Quiz: {
screen: Quiz,
navigationOptions: stackScreenNavigationOptions,
},
NewDeck: {
screen: NewDeck,
navigationOptions: stackScreenNavigationOptions,
},
NewCard: {
screen: NewCard,
navigationOptions: stackScreenNavigationOptions,
},
},
);
This is the styles definition for NewDeck.js
const styles = StyleSheet.create({
// CONTAINER styles
wrapper: {
// this was the previous container style
flex: 1,
backgroundColor: white,
alignItems: 'center',
justifyContent: 'center',
},
container: {
flex: 1,
backgroundColor: white,
alignItems: 'center',
justifyContent: 'space-between',
padding: 10,
paddingTop: 30,
paddingBottom: 5,
},
cardContainer: {
flex: 1,
justifyContent: 'flex-start',
alignSelf: 'stretch',
backgroundColor: '#fefefe',
padding: 20,
marginLeft: 30,
marginRight: 30,
marginTop: 10,
borderRadius: Platform.OS === 'ios' ? 20 : 10,
shadowRadius: 3,
shadowOpacity: 0.8,
shadowColor: 'rgba(0, 0, 0, 0.24)',
shadowOffset: {
width: 0,
height: 3,
},
marginBottom:20,
},
buttonsContainer: {
flex: 3,
alignSelf: 'stretch',
justifyContent: 'flex-start',
},
buttonContainer: {
justifyContent: 'center',
margin: 10,
},
// TEXT Styles
instructionsText: {
flex: 1,
fontSize: 20,
color: gray,
alignSelf: 'center',
textAlign: 'center',
},
// INPUTTEXT styles
textInput: {
fontSize: 27,
color: primaryColor,
alignSelf: 'stretch',
flexWrap: 'wrap',
textAlign: 'center',
marginTop: 10,
},
});
StyledButton.js (Basically, TouchableOpacity with platform-specific styling, for universal use across the app):
import React from 'react';
import { Text, TouchableOpacity, StyleSheet, Platform } from 'react-native';
import { white, gray, primaryColor, primaryColorLight, primaryColorDark} from '../utils/colors';
export default function TextButton({ children, onPress, customColor, disabled=false }) {
const disabledColor = disabled ? gray : null;
const backgroundColor = Platform.OS==='ios' ? white : disabledColor || customColor || primaryColorLight;
const borderColor = Platform.OS==='ios' ? disabledColor || customColor || primaryColorDark
const textColor = Platform.OS==='ios' ? disabledColor || customColor || primaryColor : white;
const btnStyle = Platform.OS==='ios' ? styles.iosBtn : styles.androidBtn;
const txtStyle = styles.txtDefault;
const btnColor = { backgroundColor, borderColor };
const txtColor = { color: textColor };
return (
<TouchableOpacity
onPress={onPress}
disabled={disabled}
style={[btnStyle, btnColor]}
>
<Text
style={[styles.txtDefault, txtColor]}
>
{children}
</Text>
</TouchableOpacity>
);
}
const styles = StyleSheet.create({
txtDefault: {
textAlign: 'center',
// because of bleeding of white text to colored background on android,
// enlarge text (or increase fontWeight) for better readability
fontSize: Platform.OS==='ios' ? 15 : 18,
padding: 10,
},
iosBtn: {
height: 45,
borderRadius: 7,
alignSelf: 'center',
justifyContent: 'center',
alignItems: 'center',
// ios only settings
borderColor: primaryColorDark,
borderWidth: 1,
borderRadius: 3,
paddingLeft: 25,
paddingRight: 25,
},
androidBtn: {
height: 45,
borderRadius: 5,
alignSelf: 'center',
justifyContent: 'center',
alignItems: 'center',
// android- only settings
// (padding accepts clicks, vs. margin === no-click zone)
padding: 20,
paddingLeft: 15,
paddingRight: 15,
},
});
// ios has white buttons with colored outlines and colored text
// android has colored buttons with white text
// Pass in a button color, or it defaults to the App's primary colors
just wrap the ref inside timeout
setTimeout(()=>{this.textInputRef.focus()},100)
Old Issue, but if anyone is searching through here for an answer..
It looks like the keyboard doesn't come up if you're stuck in an animation (e.g. if coming from another screen).
You can use a ref to focus on your input, but must wrap in within InteractionManager.runAfterInteractions for it to work correctly.
This is how I solved it:
export const CustomInput: FunctionComponent<Props & TextInputProps> = ({
error,
...props
}) => {
const inputRef = useRef<TextInput>(null);
useEffect(() => {
// Must run after animations for keyboard to automatically open
InteractionManager.runAfterInteractions(() => {
if (inputRef?.current) {
inputRef.current.focus();
}
});
}, [inputRef]);
return (
<View>
<TextInput
ref={inputRef}
{...props}
/>
{error && <ErrorText>{error}</ErrorText>}
</View>
);
};```
You can always use .focus on any of your TextInput when the component loads, to show the keyboard if you want to avoid the autoFocus.
componentDidMount () {
this.textInputRef.focus()
}
<TextInput
style={styles.textInput}
ref={ref => this.textInputRef = ref}
placeholder="Quiz Deck Title"
autoFocus={true}
value={this.state.title}
onChangeText={(title) => this.controlledTextInput(title)}
/>
As mentioned in the docs
Two methods exposed via the native element are .focus() and .blur() that will focus or blur the TextInput programmatically.
I only needed the 'autoFocus' prop to get this going as at today.
https://reactnative.dev/docs/textinput#autofocus

How can I change the text in TabBarIOS in React Native?

In the react native documentation I cannot find a way to change the bottom words?
<TabBarItemIOS
name="greenTab"
icon={_ix_DEPRECATED('more')}
accessibilityLabel="Green Tab"
selected={this.state.selectedTab === 'greenTab'}
onPress={() => {
this.setState({
selectedTab: 'greenTab',
presses: this.state.presses + 1
});
}}>
{this._renderContent('#21551C', 'Green Tab')}
</TabBarItemIOS>
What is the accessibilityLabel ?
The TabBarItem allows you to use one of the iOS preset icons from UITabBarSystemItem, and in your sample code it's using the "More" icon. Crucially though, the documentation for UITabBarSystemItem states:
The title and image of system tab bar items cannot be changed.
If you set the icon to either a data-uri or a local image, rather than an icon from UITabBarSystemItem, you'll be able to override the text on the item to whatever you want using the title prop.
You can try something like that for your TabBarIOS.Item with a custom icon
import React, { Component } from 'react'
import { AppRegistry, StyleSheet, Text, View, TouchableOpacity, TabBarIOS } from 'react-native'
const base64Icon = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEsAAABLCAQAAACSR7JhAAADtUlEQVR4Ac3YA2Bj6QLH0XPT1Fzbtm29tW3btm3bfLZtv7e2ObZnms7d8Uw098tuetPzrxv8wiISrtVudrG2JXQZ4VOv+qUfmqCGGl1mqLhoA52oZlb0mrjsnhKpgeUNEs91Z0pd1kvihA3ULGVHiQO2narKSHKkEMulm9VgUyE60s1aWoMQUbpZOWE+kaqs4eLEjdIlZTcFZB0ndc1+lhB1lZrIuk5P2aib1NBpZaL+JaOGIt0ls47SKzLC7CqrlGF6RZ09HGoNy1lYl2aRSWL5GuzqWU1KafRdoRp0iOQEiDzgZPnG6DbldcomadViflnl/cL93tOoVbsOLVM2jylvdWjXolWX1hmfZbGR/wjypDjFLSZIRov09BgYmtUqPQPlQrPapecLgTIy0jMgPKtTeob2zWtrGH3xvjUkPCtNg/tm1rjwrMa+mdUkPd3hWbH0jArPGiU9ufCsNNWFZ40wpwn+62/66R2RUtoso1OB34tnLOcy7YB1fUdc9e0q3yru8PGM773vXsuZ5YIZX+5xmHwHGVvlrGPN6ZSiP1smOsMMde40wKv2VmwPPVXNut4sVpUreZiLBHi0qln/VQeI/LTMYXpsJtFiclUN+5HVZazim+Ky+7sAvxWnvjXrJFneVtLWLyPJu9K3cXLWeOlbMTlrIelbMDlrLenrjEQOtIF+fuI9xRp9ZBFp6+b6WT8RrxEpdK64BuvHgDk+vUy+b5hYk6zfyfs051gRoNO1usU12WWRWL73/MMEy9pMi9qIrR4ZpV16Rrvduxazmy1FSvuFXRkqTnE7m2kdb5U8xGjLw/spRr1uTov4uOgQE+0N/DvFrG/Jt7i/FzwxbA9kDanhf2w+t4V97G8lrT7wc08aA2QNUkuTfW/KimT01wdlfK4yEw030VfT0RtZbzjeMprNq8m8tnSTASrTLti64oBNdpmMQm0eEwvfPwRbUBywG5TzjPCsdwk3IeAXjQblLCoXnDVeoAz6SfJNk5TTzytCNZk/POtTSV40NwOFWzw86wNJRpubpXsn60NJFlHeqlYRbslqZm2jnEZ3qcSKgm0kTli3zZVS7y/iivZTweYXJ26Y+RTbV1zh3hYkgyFGSTKPfRVbRqWWVReaxYeSLarYv1Qqsmh1s95S7G+eEWK0f3jYKTbV6bOwepjfhtafsvUsqrQvrGC8YhmnO9cSCk3yuY984F1vesdHYhWJ5FvASlacshUsajFt2mUM9pqzvKGcyNJW0arTKN1GGGzQlH0tXwLDgQTurS8eIQAAAABJRU5ErkJggg=='
class ReactNativePlayground extends Component {
constructor(props) {
super(props)
this.state = {
selectedTab: "more",
tabBarItemTitle: "More"
}
}
render() {
return (
<TabBarIOS>
<TabBarIOS.Item selected={this.state.selectedTab === "more"}
title={this.state.tabBarItemTitle}
icon={{uri: base64Icon, scale: 3}}>
<View style={styles.container}>
<TouchableOpacity onPress={ (event) => { this._changeTabItemTitle() } }>
<Text style={styles.button}>Tap to Change Item Title</Text>
</TouchableOpacity>
</View>
</TabBarIOS.Item>
</TabBarIOS>
);
}
_changeTabItemTitle() {
this.setState({ tabBarItemTitle: "New More" })
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
},
button: {
fontSize: 20,
color: "white",
textAlign: 'center',
backgroundColor: "#1155DD",
borderRadius: 5,
height: 30,
margin: 30,
},
});
AppRegistry.registerComponent('ReactNativePlayground', () => ReactNativePlayground);