Keyboard Handling in React Native - react-native

How to make your app respond gracefully on keyboard appearance?
So far I have tried keyboard-aware-scroll, keyboardspacer and keyboard Avoiding view
Keyboard avoiding view didn't help at all I have tried it several times but it doesn't even respond to keyboard appearance.
Keyboardspacer gracefully works but in many cases it destroys the whole UI by crushing other view
keyboardaware scroll works when there is no scroll in the app but for long forms it doesn't work.
android:windowSoftInputMode="adjustPan" only works for android
What are the other options that we have for the app to gracefully respond when keyboard appears.
What do you use in your apps?

If none of these libraries does what you need, you can adjust your view manually by using the Keyboard module (docs at https://facebook.github.io/react-native/docs/keyboard)
With it you can react when you know a keyboard opens or closes, like so:
import * as React from 'react';
import { Keyboard } from 'react-native';
class MyComponent extends React.Component {
componentDidMount() {
this.keyboardDidHideListener = Keyboard.addListener('keyboardDidHide', this.keyboardDidHide);
this.keyboardDidShowListener = Keyboard.addListener('keyboardDidShow', this.keyboardDidShow);
}
componentWillUnmount() {
this.keyboardDidHideListener.remove();
this.keyboardDidShowListener.remove();
}
keyboardDidShow = () => {
//Fix your view for when a keyboard shows
};
keyboardDidHide = () => {
//Fix your view for when a keyboard hides
};
//Rest of component...
}

For my projects I use react-native-keyboard-aware-scroll-view as well as KeyboardAvoidingView (try to play with behavior prop, it depends on your styling).
Take a look in Android configuration section in docs of react-native-keyboard-aware-scroll-view. I think it's something that you're looking for.

You can find following usefull answer related your question.
Q.How to change the Softkeyboard “Enter” button Text in android?
https://stackoverflow.com/a/53098939/6477946
Q. How to close or hide SoftKeyBoard
https://stackoverflow.com/a/53077131/6477946

Related

How to prevent user interaction during screen transition animation?

When navigating between screens using the StackNavigator with a fade transition, a user is able to click during the transition animation and possibly hit a TouchableOpacity on the screen that is being navigated away from. The TouchableOpacity registers the hit and thus the app responds accordingly. This is causing issues for "fast clicking" users where they click a button to navigate to a new screen and immediately click where they think a new button will be, but in reality is clicking a button on the previous screen.
Is there a way to prevent any user interaction during these transition animations? I have tried setting the transition duration to 0 like so:
transitionConfig: () => ({
transitionSpec: {
duration: 0
}
})
but the issue still occurs.
I do not want to disable the animation completely, because it is quick enough for most users and they like the animation.
So in your case you can do several things
You can use React Native Activity Indicator -> View
You can use Overlay Library -> react-native-loading-spinner-overlay -> View GitHub
If you like to make loading like facebook / instagram -> then use react-native-easy-content-loader -> View GitHub
you need to flag screen before navigating away; disabling all touchs.
an easy way would be to have a reusable hook that return a transparent absolute positioned View that cover entier page and a callback to enable it;
so you flow will be; enable this which will overlap whole screen and capture any clicks basically disabling them;
something more like:
function useOverlay(){
const [isVisible, toggle] = React.useState(false);
const Component = React.memo(()=><View style={styles.transparentAbsolute} />,[])
return [toggle, isVisible ? Component : null];
}
then inside your Screen before you call navigate just call toggle
and include Component at top of you screen;
export default function TabOneScreen({ navigation }: RootTabScreenProps<'TabOne'>) {
const [ toggle, component ] = useOverlay();
return (
<View style={styles.container}>
{component}
<Button onPress={()=>{toggle(true); navigation.navigate('Home');} title="go home" />
</View>
);
}

How to get current routes size of wix/react-native-navigation?

I'm trying to handle the back button on android since my React Native app has custom logic on the back button pressed for the root screen...Is there any method like Navigation.getCurrentRoutes()
in order to do something like this:
handleBackButton = () => {
if(Navigation.getCurrentRoutes().size()>1) {
return true; // addEventListener listens for the native hardware back button press and will ignore it
}
... customLogic
return false; // will execute the native back press (and exit the app)
}
"react-native-navigation": "3.0.0-alpha.2"
It turns out that there is not such a method and the two options are:
1) Handle back buttons on your own (overriding) or
2) just add your custom logic into componentWillUnmount() and continue using the native react-native-navigation
options 2 worked for me
reference: https://github.com/wix/react-native-navigation/pull/4226#issuecomment-433683885
https://github.com/wix/react-native-navigation/issues/4231

How to add Android Back Handler for a particular screen?

I have three screens MyVault, Add Doc and Add Repo. From Myvault there is one button add new doc by clicking on that Add Doc will open. Now in Add doc if user presses Back button then I want a confirmation pop up. I have one button inside add doc screen which opens Add repo screen where user can select one repo and when they click add that screen will be popped and add doc screen will be refreshed with the repo data. If I add a listener in ComponentDidMount and then remove it in ComponentWillUnmount then the issue is that even when I press back on Add repo then also the popup comes. I don't want popup on any other screens, I just want it on Add doc.
Note: I am using react native router flux for routing
I have posted this issue on this link also : https://github.com/facebook/react-native/issues/15248
As per react-native-router-flux documentation, event handlers can be added to buttons. You can use onExit, onLeft or onRight. Something like:
<Scene
key="AddDoc"
component={AddDoc}
onExit={() => console.log('your modal pop up logic')}
/>
I was able to do it with the help of onEnter and onExit props of react-native-router-flux
Try the below method
import React from 'react';
import {View, Text, AlertPlatform,BackAndroid} from 'react-native';
class App extends React.Component {
constructor(props) {
super(props);
}
onBackAndroid = () => {
backButtonPressedOnceToExit ? BackAndroid.exitApp() : "";
backButtonPressedOnceToExit = true;
setTimeout(() => {backButtonPressedOnceToExit = false;}, 2000);
return true;
}
componentWillMount = () => BackAndroid.addEventListener('hardwareBackPress', this.onBackAndroid.bind(this));
componentWillUnmount = () => {
BackAndroid.removeEventListener('hardwareBackPress', this.onBackAndroid.bind(this));
}
render() {
return (
// Your code
);
}
}
export default App;

React native DrawerLayoutAndroid and Switch component doesnt work well

I have a switch component on DrawerLayoutAndroid component. When I drag the switch component, drawer component is being slided.
How do I ensure when i drag switch, drawer panel is in blocked mode.
[EDIT]
Attaching the mocks below
Mocks
Usually a tap on the Switch will toggle the switch state. If you want to make it drag as well and not let the other view become the responder, you can do that by implementing GestureResponseHandler. Something like this.
const RespondHandler = {
onStartShouldSetResponder: function (e) {
return true;
},
onResponderGrant: function (e) {
return true;
}
};
<Switch {...RespondHandler}/>

NavigatorIOS - Is there a viewDidAppear or viewWillAppear equivalent?

I'm working on porting an app to React-Native to test it out. When I pop back to a previous view in the navigator stack (hit the back button) I'd like to run some code. Is there a viewWillAppear method? I see on the Navigator there is a "onDidFocus()" callback which sounds like it might be the right thing.. but there doesn't appear to be anything like that on NavigatorIOS
I find a way to simulate viewDidAppear and viewDidDisappear in UIKit,
but i'm not sure if it's a "right" way.
componentDidMount: function() {
// your code here
var currentRoute = this.props.navigator.navigationContext.currentRoute;
this.props.navigator.navigationContext.addListener('didfocus', (event) => {
//didfocus emit in componentDidMount
if (currentRoute === event.data.route) {
console.log("me didAppear");
} else {
console.log("me didDisappear, other didAppear");
}
console.log(event.data.route);
});
},
For people who are using hooks and react navigation version 5.x, I think you can do this to expect similar behavior of viewDidAppear:
import React, {useCallback } from "react";
import { useFocusEffect } from "#react-navigation/native";
const SomeComponent = () => {
useFocusEffect(
useCallback(() => {
//View did appear
}, [])
);
//Other codes
}
For more information, refer https://reactnavigation.org/docs/use-focus-effect/
Here is a solution to simulate viewDidAppear with latest React Navigation version:
componentDidMount() {
var currentRoute = this.props.navigation.state.routeName;
this.props.navigation.addListener('didFocus', (event) => {
if (currentRoute === event.state.routeName) {
// VIEW DID APPEAR
}
});
}
Thanks Jichao Wu for the idea :)
If you are using React Navigation, use this:
componentDidMount(){
this.props.navigation.addListener('focus', () => {
// put your code here
});
}
Basically you are adding a focus event when component is first mounted. It will be called whenever (including the first time too) the component is focused. Ideally you'd also need to remove listener on unmount by capturing the value returned from addListener call and call that returned value (which is actually the unsubscribe function).
I've created a custom button with onLeftButtonPress to handled the back to run code as per https://github.com/facebook/react-native/issues/26
The way to get around it is to either set your custom back button on the left side, or to implement - viewWillDisappear: in iOS.
You can use ComponentWillMount or if you're leaving the view you can use ComponentWillUnmount which will run some code on exit.