React Native, scrolling TextInput behind a ToolbarAndroid - reactjs

I've been stuck on the following issue for awhile now. I have a ToolbarAndroid component and a TextInput component:
<View style={{flex: 1}}>
<ToolbarAndroid
navIcon={require('./ic_menu_black_24dp.png')}
onIconClicked={() => this.drawer.openDrawer()}
style={styles.titleView}
title="Blah"
titleColor="black"
/>
<ScrollView>
<TextInput
{...this.props}
multiline={true}
onChange={(event) => {
this.setState({
text: event.nativeEvent.text,
height: event.nativeEvent.contentSize.height,
color: 'black'
});
}}
style={{fontSize: 14, textAlignVertical: 'top', height: Math.max(60, this.state.height)}}
value={this.state.text}
placeholder="Spread your message!"
placeholderTextColor='lightslategray'
underlineColorAndroid='white'
enablesReturnKeyAutomatically={true}
returnKeyType="done"
maxLength={1000}
/>
</ScrollView>
</View>
My TextInput box is auto-expanding which means it grows as it types. The input also re-focuses on top of the keyboard as it grows. However, as it grows to be bigger than my screen, it doesn't scroll behind the Toolbar. Instead, it pushes the toolbar off the screen. I'd like it to scroll behind the toolbar but I can't seem to get it to work.
Any help would be greatly appreciated.
Thanks

Related

Why is my Text Input getting activated only at the width of PlaceHolder?

I am building an Android specific app using React-Native.
In this app I am trying to build a custom TextInputField which can be re-used. This is my Custom Function Component
function AppTextInput({ icon, ...otherProps }) {
return (
<View style={styles.container}>
{icon && (
<MaterialCommunityIcons
name={icon}
size={20}
color={colors.medium}
style={styles.icon}
/>
)}
<TextInput style={customStyles.text} {...otherProps} />
</View>
);
}
const styles = StyleSheet.create({
container: {
backgroundColor: colors.light,
borderRadius: 25,
flexDirection: "row",
width: "100%",
padding: 15,
marginVertical: 10,
},
icon: {
margin: 3,
marginRight: 7,
},
});
export default AppTextInput;
I call this component from my App.js like so
<AppTextInput
autoCapitalize="none"
autoCorrect={false}
icon="email"
keyboardType="email-address"
placeholder="Email"
/>
The issue here is, this field is set-to focus only when I touch on the width occupied by placeholder text and not the entire text field. What am I doing wrong?
The focus effect will only happen when you press on the text input itself, and if you give it a background color you will find out that your text input is small and the pressable area that will trigger the focus effect is small (Only the text input area)
The solution is to make the whole View that contain the input and the icon trigger the focus via useRef like this:
export default function AppTextInput({ icon, ...otherProps }) {
const textInput = React.useRef(null);
function handleClick() {
textInput.current.focus();
}
return (
<Pressable style={styles.container} onPress={handleClick}>
{icon &&
<MaterialCommunityIcons
name={icon}
size={20}
color={colors.medium}
style={styles.icon}
/>}
<TextInput ref={textInput} {...otherProps} />
</Pressable>
);
}
Also replace the View with Pressable to be able to use onPress.
Try this simple solution,
<TextInput style={[customStyles.text, { flex: 1 }]} {...otherProps} />

TextInput Width - React Native

I have a TextInput in my React Native App. All this while I was using simulator "iPhone X" and it was working fine. Now I changed my simulator to "iPhone 5" and the width doesn't match.
<TextInput
value={value}
placeholder='Search Here...'
onChangeText={(text)=>{this.handleSearch(text)}
onTouchStart={()=>{this.setTempNotifications()}
style={{ height: 40, width: 290}}
autoCapitalize='none'
selectTextOnFocus={true}
/>
I had set the width to "290". How do I make my TextInput width flexible???? It has to fit all phone screens and I do not have to fix a width.
You don't really have to give a width value. Only the height is enough to make the TextInput span across its parent.
export default function App() {
return (
<View style={{flex: 1}}>
<TextInput
placeholder='Search Here...'
style={{ height: 40, borderWidth: 1}}
autoCapitalize='none'
selectTextOnFocus={true}
/>
</View>
);
}
The containing view can have padding or margin for appropriate gutter space

KeyboardAvoidingView doesn't work inside tab navigation

I'm using the built-in KeyboardAvoidingView in react native and when I use the code below in a screen where you can't see the tabs (like in a modal) it works perfectly fine and the keyboard doesn't cover any content whatsoever, but when I use the exact same code but in a screen that is used in tab navigation the keyboard covers some content, it's like the KeyboardAvoidingView doesn't take into consideration the height of the bottom tabs
Here's my code:
<KeyboardAvoidingView style={{flex: 1}} behavior="padding">
<ScrollView keyboardShouldPersistTaps="handled">
{content}
</ScrollView>
<TextInput
style={{height: 50, width: "100%", backgroundColor: "red"}}
placeholder="Test input"
/>
</KeyboardAvoidingView>

How to increase size of view(automatically) if the size of text increases in react native

I am making a UI design in react native i have made a card of categories i want to increase the width of view if category name is long. but i am not understanding how to do that.Please help here is my code.
<View style={styles.CardMainView}>
<View style={styles.ThirdLayerStyle} />
<View style={styles.SecondLayerStyle} />
<View style={styles.FirstLayerStyle}>
<Image resizeMode={'contain'} style={styles.CatImageStyle}
source={require('../../Assets/Images/doccatImage.png')}
/>
</View>
<Text numberOfLines={1} style={{color:'#fff' , fontSize:15, top:28 , marginLeft:25 , marginRight:20, fontFamily: "poppinsregular"}}>Orthopaedic</Text>
</View>
</View>
CardMainView:{
flexDirection:'row',
borderRadius:4,
backgroundColor:"#1abc9c",
width:190,
height:80,
elevation:3,
shadowColor:'#000',
overflow:'hidden',
},
if you do not set width for component, that component can be resizable if the content size change.
also, I write a component which expands on height if the text size increased.
set height: 0 on state
and add this function to class for focusing on text input
focus () {
this.textInput && this.textInput.focus()
}
and add this component to return
<TextInput
{...this.props}
ref={(view) => (this.textInput = view)}
multiline
onContentSizeChange={(event) => {
if (event && event.nativeEvent && event.nativeEvent.contentSize) {
this.setState({
height: event.nativeEvent.contentSize.height
})
}
this.props.onContentSizeChange && this.props.onContentSizeChange(event)
}}
style={[this.props.style, { height: Math.max(35, this.state.height) }]}
/>
hopefully, this can help you or get an idea ;)
I think you can control your size with give a padding innermost component, when you give a padding your component will increase with your text size.

react native Scroll View doesn't scroll from inside text input

I added multi Text input inside a scroll view. the problem is when I want to scroll down from inside of a text input, I put my finger inside a text input and scroll down but it doesn't scroll down the page, is there a way to fix this?
here is a sample code:
export default class ScrollViewWithTextInput extends React.Component {
render() {
<ScrollView>
<TextInput
style={styles.input}
placeholder={'توضیحات'}
underlineColorAndroid='transparent'
/>
<TextInput
style={styles.input}
placeholder={'توضیحات'}
underlineColorAndroid='transparent'
/><TextInput
style={styles.input}
placeholder={'توضیحات'}
underlineColorAndroid='transparent'
/><TextInput
style={styles.input}
placeholder={'توضیحات'}
underlineColorAndroid='transparent'
/>
<TextInput
style={styles.input}
placeholder={'توضیحات'}
underlineColorAndroid='transparent'
/>
<TextInput
style={styles.input}
placeholder={'توضیحات'}
underlineColorAndroid='transparent'
/><TextInput
style={styles.input}
placeholder={'توضیحات'}
underlineColorAndroid='transparent'
/><TextInput
style={styles.input}
placeholder={'توضیحات'}
underlineColorAndroid='transparent'
/>
</ScrollView>
}}
const styles = StyleSheet.create({
Container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
marginTop: 8
},
input: {
width: 350,
height: 100,
margin: 5,
borderColor: 'black',
borderWidth: 2,
textAlign: 'right'
}})
For some reason setting multiline={true} to the TextInput worked for me.
Not exactly sure why. Stranger still, it will not work if you also have keyboardType='numeric'.
Use each input as a component. try something like this:
<TouchableOpacity onPress={()=>this.input.focus()} >
<View pointerEvents="none" >
<TextInput ref = {(input) => this.input = input} />
</View>
</TouchableOpacity>
This will do the trick
Try to adjust the height of the input.
I don't really understand why but it solved my problem.
setting
<ScrollView keyboardShouldPersistTaps="always"
in combination with the textInout component below (custom component that i created for text inputs to solve this issue) solved my problem:
<TouchableOpacity
activeOpacity={1}
onPress={()=>this.input.focus()}>
<View
pointerEvents="none">
<TextInput
ref = {(input) => this.input = input}
/>
</View>
</TouchableOpacity>
Update
a better expression might be:
constructor(props) {
super(props);
this._keyboardDidHide = this._keyboardDidHide.bind(this)
this.onSubmitEditing = this.onSubmitEditing.bind(this)
}
componentWillMount () {
this.keyboardDidHideListener = Keyboard.addListener('keyboardDidHide', this._keyboardDidHide)
};
componentWillUnmount () {
this.keyboardDidHideListener.remove();
}
_keyboardDidHide(){
this.input.blur()
}
and then the expression above for the TextInput component. because in the previous expression when you press back and the keyboard hides, and you tap on that input again, the keyboard doesn't open, because that input is already focused. so you need to blur and then focus again.
this is my idea, maybe you might perform this in a more creative way :)
btw don't forget to import Keyboard from 'react-native' if you use my expression.

Resources