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

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.

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} />

Why is scrollToEnd() not working on Android?

I currently have it set such that when the user opens the keyboard it scrolls to the bottom when the scroll view shrinks.
<ScrollView
contentContainerStyle={{ flexGrow: 1 }}
ref={(ref) => (this.scrollView = ref)}
>
<TextInput
onFocus = {this.scrollDown}
/>
scrollDown = () => {
this.scrollView.scrollToEnd();
}
This works on IOS perfectly fine, but doesn't seem to be working on Android.
Android:
https://imgur.com/a/9HfaCMd
iOS:
https://imgur.com/a/dB1WeoW
--Update--
After looking your record, it doesn't seems caused by scrollToEnd.
What you need may be KeyboardAvoidingView
It can automatically adjust either its height, position, or bottom padding based on the keyboard height.
const keyboardVerticalOffset = Platform.OS === 'ios' ? 40 : 0 //update 2 something like this
...
<KeyboardAvoidingView
behavior='position' //update 2
keyboardVerticalOffset={keyboardVerticalOffset} //update 2
style={styles.container}
>
<TouchableWithoutFeedback onPress={Keyboard.dismiss}>
<View style={styles.inner}>
<Text style={styles.header}>Header</Text>
<TextInput placeholder="Username" style={styles.textInput} />
<View style={styles.btnContainer}>
<Button title="Submit" onPress={() => null} />
</View>
</View>
</TouchableWithoutFeedback>
</KeyboardAvoidingView>

TextInput weird behaviour in React-Native

I have the following TextInput,
<TextInput
style={[
styles.inputField,
isEmailError && { borderColor: color.delete },
]}
placeholder={'E-mail'}
placeholderTextColor={color[colorScheme].textMuted}
autoCapitalize={'none'}
autoCorrect={false}
value={userCredentials.email}
onChangeText={onChangeEmail}
onSubmitEditing={passwordInput.current && passwordInput.current.focus}
blurOnSubmit={false}
returnKeyType={'next'}
keyboardType="email-address"
/>
When I click anywhere else outside the keyboard(let's say a button), the expected behaviour is that the button will get clicked, however, in here, first click always closes the keyboard then I have to press again for whatever element i was trying to reach.
This is because of scroll view. Add props keyboardShouldPersistTaps in your scrollview as below to solve error :
<ScrollView
keyboardShouldPersistTaps="handled"
keyboardDismissMode="interactive"
>
...
...
</ScrollView>
You can find more detail here
Maybe try this:
import DismissKeyboard from 'dismissKeyboard';
<TouchableWithoutFeedback onPress={()=>{DismissKeyboard()}}>
<View style={Styles.container}>
<TextInput />
</View>
</TouchableWithoutFeedback>

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, scrolling TextInput behind a ToolbarAndroid

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

Resources