I am trying to disabling the physical device back in android only in some screens. Trying the below code is not working. Any idea?
import { RouterExtensions } from "nativescript-angular";
import * as application from "application";
import { AndroidApplication, AndroidActivityBackPressedEventData } from "application";
import { isAndroid } from "platform";
export class ItemComponent implements OnInit {
constructor(private router: Router) {}
ngOnInit() {
if (!isAndroid) {
return;
}
application.android.on(AndroidApplication.activityBackPressedEvent, (data: AndroidActivityBackPressedEventData) => {
data.cancel = true; // prevents default back button behavior
});
}
}
#Override
public void onBackPressed() {
if (!shouldAllowBack()) {
doSomething();
} else {
super.onBackPressed();
}
}
Add this code in your activity-
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
// Your Code Here. Leave empty if you want nothing to happen on back press.
}
For more information visit this link.
Back button is controlled at Activity level, NativeScript uses one single Activity and all your pages / routes are fragments inside that.
So you don't have to call it on every page / component. Add the listener to your app component and check the router to know which page you are at and cancel the back event.
Use location and check if location consists the desired path(as mentioned in routing file) where you want to use your custom function.
import { Location } from '#angular/common';
constructor(private _location: Location
){}
if (application.android) {
application.android.on(AndroidApplication.activityBackPressedEvent, (data: AndroidActivityBackPressedEventData) => {
const path = this._location.path();
console.log(`path i s--> ${path}`);
switch (path) {
case '/Screen 1':
data.cancel = true;
break;
case '/Screen 2':
//do something else
break;
});
}
Related
I have extended androidx.appcompat.app.AppCompatActivity to capture key event in a NativeScript-Vue project. Now, my problem becomes how to notify the Vue app that a key even has been captured. More importantly, what is the right way to notify the Vue app ('cause I can think of some not too correct way to solve the problem)?
At the end, I settled at the most straightforward solution. In activity.android.js, I implemented a simple listener pattern:
androidx.appcompat.app.AppCompatActivity.extend("org.myApp.MainActivity", {
keyUpListener: null,
registerListener(name, func) {
if (name == "keyUp") {
this.keyUpListener = func;
}
else {
throw new Error(`There's not a type of listener called ${name}.`);
}
},
unregisterListener(name) {
if (name == "keyUp") {
this.keyUpListener = null;
}
else {
throw new Error(`There's not a type of listener called ${name}.`);
}
},
onKeyUp: function (keyCode, event) {
if (this.keyUpListener) {
let result = this.keyUpListener(keyCode, event);
if (result != null) {
return result;
}
}
return superProto.onKeyUp.call(this, keyCode, event);
},
[... snip ...]
Then, in my .vue file, I simply register a listener to the extended Activity:
import { android as androidApp } from "tns-core-modules/application";
[... snip ...]
androidApp.foregroundActivity.registerListener(
"keyUp",
this.onKeyUp
);
If there's a better Vue or NativeScript way to handle this problem, I would love to learn about it.
I have an app (Webview exactly) and I'm trying to handle the Android hardware button to return from the second page for example to the first one. My problem now is the button won't close the app anymore, and I don't know what should I do. Here is my code:
export default class App extends Component {
constructor(props) {
super(props)
this.state={
};
this.handleBackButtonClick = this.handleBackButtonClick.bind(this);
}
componentWillMount() {
BackHandler.addEventListener('hardwareBackPress',this.handleBackButtonClick);
}
componentWillUnmount() { BackHandler.removeEventListener('hardwareBackPress',this.handleBackButtonClick);
}
onNavigationStateChange(navState){
console.log(JSON.stringify(navState));
canGoBack = navState.url == initialUrl && !navState.loading
}
handleBackButtonClick() {
this.refs[WEBVIEW_REF].goBack();
return true;
}
The return value of handleBackButtonClick determines whether the app is to be kept running or not.
Currently, you are always returning true. Instead, you could check whether the current navigation state is such that you would like to close the app, and return false accordingly.
handleBackButtonClick() {
const canGoBack = someCalculation();
if(canGoBack)
this.refs[WEBVIEW_REF].goBack();
}
return canGoBack;
}
I am writing a react native app and need to implement keyboard events inside components.
I tried with following code and did not success.
import { DeviceEventEmitter } from 'react-native';
export default class KeyEvent {
static onKeyDownListener(cb) {
KeyEvent.removeKeyDownListener();
console.log('Key Down');
this.listenerKeyDown = DeviceEventEmitter.addListener('onKeyDown', cb);
}
static removeKeyDownListener() {
if (this.listenerKeyDown) {
this.listenerKeyDown.remove();
}
}
static onKeyUpListener(cb) {
console.log('Key up');
KeyEvent.removeKeyUpListener();
this.listenerKeyUp = DeviceEventEmitter.addListener('onKeyUp', cb);
}
static removeKeyUpListener() {
if (this.listenerKeyUp) {
this.listenerKeyUp.remove();
}
}
}
Call inside componentDidMount function relevant component as follows.
componentDidMount() {
console.log('componentDidMount');
// if you want to react to keyDown
KeyEvent.onKeyDownListener((keyCode) => {
console.log(`Key code pressed: ${keyCode}`);
});
// if you want to react to keyUp
KeyEvent.onKeyUpListener((keyCode) => {
console.log(`Key code pressed: ${keyCode}`);
});
}
componentWillUnmount() {
console.log('componentWillUnmount');
// if you are listening to keyDown
KeyEvent.removeKeyDownListener();
// if you are listening to keyUp
KeyEvent.removeKeyUpListener();
}
Can anyone help me to fix this or suggest any other way of doing this. I need to press a button on enter key down.
As per react native doc, you can attach below events to keyboard.
keyboardWillShow
keyboardDidShow
keyboardWillHide
keyboardDidHide
keyboardWillChangeFrame
keyboardDidChangeFrame
So if you want pressed key event then you need to attach event to input field like below.
<TextInput
onKeyPress={this.handleKeyDown}
placeholder="Enter text here..."
/>
handleKeyDown: function(e) {
if(e.nativeEvent.key == "Enter"){
dismissKeyboard();
}
},
According to react-native docs BackAndroid component with simple callback should not allow exit the app on back button press, but it looks like the event listener isn't called at all.
BackAndroid.addEventListener('hardwareBackPress', function() {
return true;
});
What should be changed to allow event listener triggering?
Based on the original github issue, Satyajit Sahoo provided a workable solution:
add the following to MainActivity.java:
#Override
public void onBackPressed() {
if (mReactInstanceManager != null) {
mReactInstanceManager.onBackPressed();
} else {
super.onBackPressed();
}
}
You are missing this.goBack(); before you return true.
BackAndroid.addEventListener('hardwareBackPress', function() {
this.goBack();
return true;
});
I am using WizarDroid library, and creating a simple Wizard.
What I am trying to do is at the final step I want to disable Back button at the bottom. I have searched every where and the documentation is not helping me.
Here is my Basic Wizard code:
public class FormWizard extends BasicWizardLayout
{
public FormWizard()
{
super();
}
#Override
public WizardFlow onSetup()
{
return new WizardFlow.Builder()
/*
* Mark this step as 'required', preventing the user from advancing to the
* next step without selecting one option.
*/
.addStep(Form1.class, true)
.addStep(Form2.class, true)
.addStep(Form3.class)
.create();
}
#Override
public void onWizardComplete()
{
super.onWizardComplete();
// Terminate the wizard
getActivity().finish();
}
}
The Form1,Form2 and Form3 are simply extending WizardStep and showing some data to user.
In the documentation the wizard.goNext(); method is defined but it is not available in my scenario.
I simply want to disable the user to go back after they reach at Form3 or final step.
If you are talking about disabling the software/hardware (next to the home button and menu button) then you simply have to handle the onPress yourself. Example:
//FOR API 5-
#Override
public void onBackPressed() {
Toast.makeText(getApplicationContext(), "Can't go back", Toast.LENGTH_LONG).show();
}
//FOR API 6+
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
Toast.makeText(getApplicationContext(), "Can't go back", Toast.LENGTH_LONG).show();
return true;
} else {
return super.onKeyDown(keyCode, event);
}
}