I currently have a react native app with one main screen that navigates to a second screen that has 3 text inputs. The problem I am having only occurs on Android. On the second screen, whenever a text input is in focus and I try to navigate back via react navigations’ back button, the keyboard hides, then reappears, then hides, and then transitions back to the first screen. It seems when I initially press the back button the inputs focus is blurred, then when I let go it refocuses on the input and then blurs it again and then navigates back. Not sure why this is happening on Android. It works as expected on iOS. Any solutions?
Thanks!
Did you have been manipulating keyboardHandlingEnabled prop? It can be related to this.
Or you can just hook back press event using This Guide and blur your text input first like following.
function ScreenWithCustomBackBehavior() {
// ...
useFocusEffect(
React.useCallback(() => {
const onBackPress = () => {
if (isSelectionModeEnabled()) {
disableSelectionMode();
return true;
} else {
return false;
}
};
BackHandler.addEventListener('hardwareBackPress', onBackPress);
return () =>
BackHandler.removeEventListener('hardwareBackPress', onBackPress);
}, [isSelectionModeEnabled, disableSelectionMode])
);
// ...
}
Related
I am trying to hide app content when the user tries to navigate away from the app, like how banking apps or outlook works. I am using appstate inactive for ios, and appstate blur+focus for android. This works on Android when the user pulls down the notification panel or swipes up to multitasking tray or home through a gesture.
However, if the android phone has soft buttons for navigation instead of gestures, the app doesnt show the security screen on blur. I suppose react native loses control of the app too soon for that to happen. The blur event is still triggered, but the UI remains unchanged.
I have a useEffect in a custom hook that changes the state on blur, which triggers the UI update;
const [appStateVisible, setAppStateVisible] = useState(true);
const appState = useRef(AppState.currentState);
useEffect(() => {
const androidFocusSubscription =
Platform.OS === 'android' &&
AppState.addEventListener('focus', () => {
setAppStateVisible(true);
});
const androidBlurSubscription =
Platform.OS === 'android' &&
AppState.addEventListener('blur', () => {
setAppStateVisible(false);
});
return () => {
if (androidFocusSubscription && androidBlurSubscription) {
androidFocusSubscription.remove();
androidBlurSubscription.remove();
}
};
}, []);
return appStateVisible;
And then on App.tsx, I am calling this hook to decide whether to show the security image instead of the actual app content.
The alternative would be to use FLAG_SECURE in the java code to show a white screen when the app isnt active, but I want to show a custom screen with the app logo instead of a white screen.
Any help would be greatly appreciated. Thank you.
I am building an app that has three tab navigation.
Each tab wraps a WebView and displays the uri webview is directing.
So, I have three WebViews running in an app.
/* each screen wraps a webview */
/screens
-HomeScreen
-ChatScreen
-ProfileScreen
In each screen, I have back button mapped to call webviewRef.current.goBack() just like below.
useEffect(() => {
const handleBackButtonPress = () => {
if (webviewRef.current) {
webviewRef.current.goBack();
return true;
}
return false;
};
BackHandler.addEventListener("hardwareBackPress", handleBackButtonPress);
return () =>
BackHandler.removeEventListener(
"hardwareBackPress",
handleBackButtonPress
);
}, []);
return (
<Screen>
<WebView
source={{
uri: "http://0.0.0.0:3000/",
}}
ref={webviewRef}
onMessage={handleMessage}
injectedJavaScript={script}
/>
</Screen>
);
It works seamlessly in each webviews, but the problem happens when I move on to different screen(or webview). To help you grasp, I will list the steps to generate the problem I faced.
I open the app and view HomeScreen webview.
I look around in HomeScreen webview (I can use back button)
I decide to move to ProfileScreen and touch profile icon in the tab navigation
I am on ProfileScreen webview.
I look around in ProfileScreen webview (I visit links)
I touch hardware back button and it does not work. (to elaborate, it does nothing.)
My guess is:
the cleanup function in useEffect is somehow removing 'hardwareBackPress' event..
advice appreciated.
I use ionic 3 for my app and have an issue when test on android 8.
There is an event when user swipes in application from the right bottom corner to minimize it and swipes back (or stops swiping) to the initial position. Please check animated screenshot below:
I need to open keyboard when user cancels minimization, I am looking for an appropriate events, something like onstartminimization / onendminimization or onwindowminimizestart / onwindowminimizeend to handle this issue.
pauseListener:any;
resumeListener:any;
this.platform.ready().then(() => {
this.pauseListener = this.platform.pause.subscribe(() => {
console.log('**** MINIMIZE ****');
});
this.resumeListener = this.platform.resume.subscribe(() => {
console.log('**** RESUME ****');
});
});
ionViewWillUnload() {
//remove listeners
this.pauseListener.unsubscribe();
this.resumeListener.unsubscribe();
}
I'm making a "joystick" app on android for my RC-car and I want be able to press two or more buttons at the same time to allow more precise control.
But, right now I can only press one button and the others do not respond until I release pressed button. They are even do not change their opacity, so it's not a problem in the app's logic. And click handlers also do not perform time critical operations, so I don't think that UI is just stuck.
Here's the code for my buttons:
<R.View>
{this.btn(Car.Transmission.Forward, 'Forward')}
</R.View>
<R.View flexDirection="row">
{this.btn(Car.Transmission.Left, 'Left')}
{this.btn(Car.Transmission.Stop, 'Stop')}
{this.btn(Car.Transmission.Right, 'Right')}
</R.View>
<R.View>
{this.btn(Car.Transmission.Backward, 'Backward')}
</R.View>
btn(transmission, text) {
return <MyButton
onPressIn={() => {
this.drive(transmission)
}}
onPressOut={() => {
this.drive(Car.Transmission.Neutral)
}}
text={text} />
}
export class MyButton extends React.Component {
render() {
var {onPressIn, onPressOut, text, disabled} = this.props
let textStyle = disabled ? [style.button, style.disabled] : [style.button]
return (
<R.TouchableOpacity onPressIn={onPressIn} onPressOut={onPressOut} disabled={disabled}>
<R.Text style={textStyle} >{text}</R.Text>
</R.TouchableOpacity>
)
}
}
Maybe I should not be using TouchableOpacity?
EDIT: I've almost done it, but... when I receive touch location in onPanResponderMove callback my nativeEvent.locationY value jumps like a crazy (161, 0, 163, 11, 29, ...) when I click at the same point on the screen... First, I thought this is because of USB-cable and charging, but over Wi-Fi I get the same results. That's strange. Any ideas?
I am having the most annoying situation. Ok, here goes. I am using a javascript based sliding menu for a mobile app. The "slider" works just like Facebook mobile, where you can click the button to show the menu on the left and click it again to close the menu. As an alternative, if you touch the still visible part of the page when the menu is showing it will also close. And that's it.
Problem: Note that I'm using Phonegap for this app. When I run the iOS simulator in Xcode all works fine EXCEPT if you swipeleft, for example, the page will move. I want to disable the swipe event all together. I have tried preventDefault, return false etc. Nothing seems to work. Again, my only goal is to disable touch events because for this app, I simply don't need them. Please see the javascript code for the menu show/hide below.
Thanks is advance. All is appreciated.
$(function(){
var menuStatus;
// Show menu
$("a.showMenu").click(function(){
$('#menu').show();
if(menuStatus != true){
$(".ui-page-active").animate({
marginLeft: "170px",
}, 300, function(){menuStatus = true});
return false;
} else {
$(".ui-page-active").animate({
marginLeft: "0px",
}, 300, function(){menuStatus = false});
return false;
}
});
// Menu behaviour
$("#menu li a").click(function(){
var p = $(this).parent();
if($(p).hasClass('active')){
$("#menu li").removeClass('active');
} else {
$("#menu li").removeClass('active');
$(p).addClass('active');
}
});
});
You could over-ride the $.event.special.swipe.horizontalDistanceThreshold to a larger value and prevent swipes on your page from triggering the swipe event.
Refer to Touch Events -> Swipe