React Native, Andoid: input loses focus when icon clicked - android

Faced an unexpected obstacle - when I click on the icon to clear the input, the focus from the input is lost and the click is not processed.
This only happens on Android. IOS is fine.
const onBlurHandler = (e: NativeSyntheticEvent<TextInputFocusEventData>) => {
onBlur && onBlur(e);
setFocusOff();
};
const onFocusHandler = (e: NativeSyntheticEvent<TextInputFocusEventData>) => {
onFocus && onFocus(e);
setFocusOn();
};
<TextInput
{...inputProps}
keyboardType={keyboardType}
onFocus={(e) => onFocusHandler(e)}
onBlur={(e) => onBlurHandler(e)}
placeholderTextColor={colors.light.grayscale[300]}
style={[lightInput.input, isFocusedStyles, isNonEditableStyles, isDisabledStyles, isErrorStyles]}
editable={enabled}
selectTextOnFocus={enabled}
value={value}
/>
{isInputFilled && !error && editable && enabled && (
<View style={lightInput.icon}>
<TouchableOpacity
onPress={onInputClear}>
<Close width={18} height={18} color={colors.light.grayscale[300]} />
</TouchableOpacity>
</View>
)}
Close icon has absolut position.
I tried use e.stopPropagation() and some other tricks, but it doesn't work anyway.(

Because your delete button is a button, it gets focused when pressed.
To solve this issue, you can simply create a reference textInputRef for your textinput and call textInputRef.current.focus() in your onInputClear function.

Thank your for your answers.
Also I found this solution:
add to ScrollView prop keyboardShouldPersistTaps='handled'
Also works!

Related

Changing color with event listener works on web, but not on phone

I want to change the color of a button and lauch a function when pressing it. I works on web with this code :
changeColor= event =>{
event.currentTarget.style.backgroundColor = 'salmon';
}
render(){
return(
<View style={styles.container}>
{ this.state.wordsToUse.map(word=>(
<Text style={styles.text}>{word}</Text>
))}
<Button title ="C'est deviné !" onPress={()=>{
this.motDevine()
}}/>
<Text style={styles.text}> Temps restant : {this.state.timeLeft}</Text>
{ this.state.lettersToUse.map(letter=>(
<TouchableHighlight
style={styles.buttonLetterInactive}
activeOpacity={0.6}
underlayColor="#DDDDDD"
onPressIn={()=>this.useLetter(letter)}
onLongPress={()=>this.passWords(letter)}
onPress={this.changeColor}
>
However, it does not on androids or IOS !The probleme is with the changeColor function. If I delete ' onPress={this.changeColor}", there is no bug but the color is not changed.
WHen I press the button, this is the error I get : undefined is not an object (evaluating 'event.currentTarget.style.backgroundColor = 'salmon'')
I had no idea it was even possible. Can you please explain why and what should I do to solve the problem ?

React Native: Finish current screen (component) after on press

I have a React Native app Android-based and I'm navigating from a Screen A to Screen B.
Screen B is a component that has a Text Input and uses an update button to save the new value.
Screen B
What I'm looking is to dismiss/finish Screen B after the button is pressed, and having a flow that looks like this:
Screen A -> Screen B (Finish screen and come back to) -> Screen A
Nonetheless, when I press the Back Arrow button in the Android device after I come back to Screen A the app still comes back to Screen B :(
The render method in Screen A
render() {
return (
<View style={styles.container}>
<View styleName="horizontal" style={styles.row}>
<Text style={styles.captionDarkGray}>
{this.props.user.name}
</Text>
<View style={styles.alignHorizontalRight}>
<Text
style={styles.editButton}
onPress={() =>
this.props.navigation.navigate("ScreenB", {
fieldName: "Name",
fieldValue: this.props.user.name
})
}
>
Edit
</Text>
</View>
</View>
</View>
);
}
The Screen B code is:
export class ScreenB extends Component {
constructor(props) {
super(props);
}
dimissScreen() {
// Finish this Component
}
render() {
const fieldName = this.props.navigation.getParam("fieldName", "NO-ID");
const fieldValue = this.props.navigation.getParam("fieldValue", "NO-ID");
return (
<View style={styles.container}>
<StatusBarBackground />
<View style={styles.globalBar}>
<Text style={(styles.h3, { marginLeft: 10 })}>
Update {fieldName}
</Text>
</View>
<View style={localStyles.content}>
<TextInput
placeholder={fieldValue}
defaultValue={fieldValue}
style={(styles.formFieldEditText, localStyles.editText)}
onSubmitEditing={() => this.phoneNumberInput.focus()}
keyboardType="default"
autoCapitalize="words"
autoCorrect={true}
placeholderTextColor={Colors.grayDark}
maxLength={30}
/>
<ButtonMm onPress={() => this.dimissScreen()}>Update</ButtonMm>
</View>
</View>
);
}
}
And the Stack Navigator of the Router looks like this:
export const RootAppNavigator = createStackNavigator(
{
ScreenA: {
screen: ScreenA,
navigationOptions: { header: null }
},
ScreenB: {
screen: ScreenB,
navigationOptions: { header: null }
},
OtherScreen: {
screen:...
Is there any way to sort of call finish() for Screen B (Like when we finish an Android Activity ) once the update button was pressed?
I think in this way, on back pressed the Screen A will not come back to Screen B.
Thanks in advance
You can use this in order to go back if you can not in the same stack
onPress={() => this.props.navigation.goBack(null)}
you can also use pop if you are in the same stack and want to go back to the previous screen
onPress={() => this.props.navigation.pop()}
if you want to go two screens back try this
this.props.navigation.pop(2)
This worked fine for me
this.props.navigation.replace('YourPageRoot');
please try the below code
<Button
onPress={() => goBack()}
title="Update"
/>

FlatList scrollToEnd not working in Android with Redux

ScrollToEnd() (on a FlatList) appears to have no effect in Android (or in the iOS simulator). The refs appear to be correct, and my own scrollEnd function is being called (I was desperate) but nothing changes on the screen. The effects of all the scroll functions appear to be really inconsistent - I can get scrollToOffset to work on iOS but not Android. I read that this may be because Android doesn't know the height of the items in the flatlist, but it still doesn't work with getItemLayout implemented.
There's no feedback/errors I can see which would explain why this wouldn't work. Note that I am developing with Redux, using Android 7.0 to test and am trying this in Debugging mode (using react-native run-android). The FlatList is inside a normal View (not a ScrollView).
The logic in the code is correct as far as I can tell, but calling scrollToEnd on the FlatList has no visible effect.
My render() function:
<View style={styles.container}>
<View style={styles.inner}>
<FlatList
ref={(ref) => { this.listRef = ref; }}
data = {this.getConversation().messages || []}
renderItem = {this.renderRow}
keyExtractor = {(item) => item.hash + ''}
numColumns={1}
initialNumToRender={1000}
onContentSizeChange={() => {
this.scrollToEnd();
}}
getItemLayout={(data, index) => (
{length: 50, offset: 50 * index, index}
)}
onContentSizeChange={this.scrollToEnd()}
onLayout={ this.scrollToEnd()}
onScroll={ this.scrollToEnd()}
/>
</View>
</View>
this.scrollToEnd():
scrollToEnd = () => {
console.log("scrolling func"); // This is printed
const wait = new Promise((resolve) => setTimeout(resolve, 0));
wait.then( () => {
console.log("scrolling"); // This is also printed
this.listRef.scrollToEnd(); // Throws no errors, has no effect?
});
};
Thanks so much.
Your code seems correct to me, but which version of React are you using? Starting from v16.3 the recommended way to use refs is through React.createRef(), so your code would be change to:
// constructor
constructor(props) {
super(props)
this.flatlistRef = React.createRef();
}
// inside render
<FlatList
ref={this.flatlistRef}
...
/>
// scrollToEnd
scrollToEnd = () => {
this.flatlistRef.current.scrollToEnd(); // ref.current refers to component
};
Note that this might not solve your problem, since the older usage of ref should still be valid

How to navigate faster in react native on Android and Windows Device?

Here is the code in index.js:
render() {
return (
<Navigator initialRoute = {{
id: 'firstPage'
}}
renderScene={
this.navigatorRenderScene
} />
);
}
navigatorRenderScene(route, navigator) {
switch (route.id) {
case 'firstPage':
return(<FirstPage navigator={navigator} title="First Page"/>);
case 'secondPage':
return(<SecondPage navigator={navigator} title="Second Page"/>);
}
}
Inside firstPage.js
class FirstPage extends Component {
...
<TouchableHighlight onPress={() => this.onFirstButtonPress()}>
</TouchableHighlight>
onFirstButtonPress() {
this.props.navigator.push({
id:'secondPage'
})
}
...
}
Inside secondPage.js:
<TouchableHighlight onPress={ () => this.onSecondButtonPress() } > </TouchableHighlight>
onSecondButtonPress() {
this.props.navigator.pop();
}
My intend here is after click FirstButton on FirstPage, I navigate to SecondPage. After clicking SecondButton, I return to FirstPage.
My code works, but when I click on FirstButton, I see the first page slowly disappears, and the 2nd page slowly shows up, and there is 1 or 2 seconds, they overlap each other. Is there a way I can make a clear and quick switch between the two?
The code looks fine to me. Can you check couple of things here, please :
1) You are running on Debug mode.(That boosts the performance)
2) See if you have not triggered Slow Animations in your simulator. Try clicking on Slow Animation from Debug->Slow Animation.

React Native TextInput still has focus after dismissing keyboard (cursor in the TextInput)

How can I get rid of the cursor in the text input after I dismiss the keyboard or press somewhere else?
This is just all I have for the TextInput:
<TextInput
style={styles.searchBar}
onChangeText={null}
placeholder={'What are you searching for?'}
underlineColorAndroid="transparent"
/>
I know this question is a bit old but just improving Martin's answer you could do:
componentDidMount(){
Keyboard.addListener('keyboardDidHide', this._forceLoseFocus);
}
<TextInput ref={(component) => this._textInput = component}/>
_forceLoseFocus = () => {
this._textInput.blur();
}
Tested and working with React Native 0.55.4
I guess if you dismiss the keyboard on Android with the Android-Back-Button you will have to detect a press on that button or detect when the keyboard has disappeared. To check for the keyboard:
import {
Keyboard
} from 'react-native';
class MyClass extends Component{
//...
componentDidMount () {
Keyboard.addListener('keyboardDidHide', callback)
}
//...
}
And in your callback you could then call this.refs.yourInput.blur();
And if you want to try it with detecting the Backbutton-Press, but I'm not sure if that works for detecting the keyboard disappear.

Categories

Resources