Ionic override todo el comportamiento del botón de RETROCESO para un controlador específico


Quiero ser capaz de anular el botón ATRÁS en la barra de navegación, y el botón hardware.

Quiero que esta anulación sea para un controlador específico, pero no para el resto de los controladores.

  • debe cancelarse cuando el usuario se mueve a otra pantalla

(usando uranio-unicornio iónico v1.0.0)


Mi razón es que tengo una lista de elementos. Al hacer clic en la lista se abre una página de detalles, con 3 pestañas. Cada pestaña comparte lo mismo controlador.

Sin embargo, presionando hacia ATRÁS en cualquiera de esas pestañas debe volver a la lista principal. Así es como funciona en dispositivos nativos, así es como me gustaría que funcionara en mi aplicación híbrida.


Muchas soluciones proporcionadas en línea parecen ser para versiones beta más antiguas, o para el registro fuera de los controladores.

Una solución común para trabajar con el botón de hardware Android dentro de un controlador es:

$ionicPlatform.registerBackButtonAction(function (event) {
  if($state.current.name=="home"){
    alert("button back");
  }
}, 100);

Sin embargo, esto no parece funcionar en la navegación suave botón de barra, y funciona en todos los controladores, no solo en uno.

Author: Richard Le Mesurier, 2015-08-26

6 answers

Es posible anular ambos botones en su controlador, sin ningún cambio en el código HTML.

Para resumir:

  • Botón de la barra de navegación suave - anular $rootScope.$ionicGoBack()
  • Botón Android duro - use $ionicPlatform.registerBackButtonAction()

Explicaciones detalladas a continuación.


La solución para anular el botón de retroceso de la barra de navegación suave viene de entender lo que hace Ionic cuando se presiona ese botón.

De la Ionic docs para ion-nav-back-button, ya sabemos que:

El botón se establece automáticamente en $ionicGoBack() al hacer clic/tocar.

Buscando el código fuente en ionic.paquete.js revela cómo se declara esto:

$rootScope.$ionicGoBack = function(backCount) {
    $ionicHistory.goBack(backCount);
};

Anular esto en su propio controlador es simple. Asegúrese de pasar $rootScope al controlador y simplemente modifique el código anterior. Es una buena idea tomar un puntero a la función original para que pueda restaurarla si requerido, o llame a él cuando termine con su procesamiento personalizado.

// grab pointer to original function
var oldSoftBack = $rootScope.$ionicGoBack;

// override default behaviour
$rootScope.$ionicGoBack = function() {
    // do something interesting here

    // uncomment below line to call old function when finished
    // oldSoftBack();
};

La solución para anular el botón de RETROCESO del hardware de Android, para un solo controlador, proviene del valor de retorno de la función registerBackButtonAction(), que realiza la cancelación del registro de la anulación.

Llama a ese método de cancelación de registro en el controlador $scope.$on('$destroy'....

var doCustomBack= function() {
    // do something interesting here
};

// registerBackButtonAction() returns a function which can be used to deregister it
var deregisterHardBack= $ionicPlatform.registerBackButtonAction(
    doCustomBack, 101
);

$scope.$on('$destroy', function() {
    deregisterHardBack();
});

Más detalles aquí:


Una solución completa requeriría lo siguiente:

  • anular el botón de retroceso de la barra de navegación suave
  • anular el botón de retroceso duro de Android
  • scope sería un único controlador
  • comportamiento predeterminado restaurado

El siguiente código ilustra cómo se puede hacer esto:

// run this function when either hard or soft back button is pressed
var doCustomBack = function() {
    console.log("custom BACK");
};

// override soft back
// framework calls $rootScope.$ionicGoBack when soft back button is pressed
var oldSoftBack = $rootScope.$ionicGoBack;
$rootScope.$ionicGoBack = function() {
    doCustomBack();
};
var deregisterSoftBack = function() {
    $rootScope.$ionicGoBack = oldSoftBack;
};

// override hard back
// registerBackButtonAction() returns a function which can be used to deregister it
var deregisterHardBack = $ionicPlatform.registerBackButtonAction(
    doCustomBack, 101
);

// cancel custom back behaviour
$scope.$on('$destroy', function() {
    deregisterHardBack();
    deregisterSoftBack();
});

Este problema se ha discutido en las páginas de foros y problemas de Ionic:

 61
Author: Richard Le Mesurier,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:26:36

Tomé la sugerencia de Richard y la puse en un servicio para hacerla más reutilizable.

El Controlador

angular.module('MainApp').controller('MyController', ['backButtonOverride'], function (backButtonOverride) {
    // override back button for this controller
    backButtonOverride.setup($scope, function() {
        console.log("custom back");
    });
}

El Servicio

angular.module('MainApp.services', []).factory('backButtonOverride', function ($rootScope, $ionicPlatform) {
    var results = {};

    function _setup($scope, customBackFunction) {
        // override soft back
        // framework calls $rootScope.$ionicGoBack when soft back button is pressed
        var oldSoftBack = $rootScope.$ionicGoBack;
        $rootScope.$ionicGoBack = function() {
            customBackFunction();
        };
        var deregisterSoftBack = function() {
            $rootScope.$ionicGoBack = oldSoftBack;
        };

        // override hard back
        // registerBackButtonAction() returns a function which can be used to deregister it
        var deregisterHardBack = $ionicPlatform.registerBackButtonAction(
            customBackFunction, 101
        );

        // cancel custom back behaviour
        $scope.$on('$destroy', function() {
            deregisterHardBack();
            deregisterSoftBack();
        });
    }

    results.setup = _setup;
    return results;
});
 6
Author: oalbrecht,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-04-20 03:02:28

¿Está hablando de la navegación suave como en el botón atrás en la barra de encabezado de iones o en la barra de navegación de iones? porque es una solución fácil. Simplemente haga su propia barra de encabezado personalizada para esa plantilla. así que en esa plantilla de estado sólo use algo como esto.

<div class="bar bar-header bar-positive">
        <button ng-click="someCustomFunction()" class="button button-clear button-light icon-left ion-chevron-left">Go Back</button>
</div>
 2
Author: Jess Patton,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-08-27 11:46:28

La respuesta anterior para anular ro rootScope.ion ionicGoBack funciona parcialmente.

El problema es con la forma de cancelar el registro de software. Probé el antedicho scope alcance.$on ('destroy destroy', a_function) y también el nuevo scope scope.$a('$ionicView.beforeLeave', a_function), ninguno funciona.

La razón de esto: el nuevo controlador se introducirá antes de que el deregisterSoftBack falle. Así que modifiqué un poco la solución para que funcionara.

  1. Cambiar el

    var oldSoftBack = $rootScope.$ionicGoBack
    

    A

    $rootScope.oldSoftBack = $rootScope.$ionicGoBack
    
  2. Cancelar el registro en ro rootScope.$on ("stat stateChangeStart", your_function), el código es:

    if ($rootScope.oldSoftBack) {
        $rootScope.$ionicGoBack = $rootScope.oldSoftBack;
        $rootScope.oldSoftBack = null;
    }
    
 1
Author: raven.zuo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-01-26 10:59:26

Esta es mi solución:)

Coloque esta parte del código en su aplicación.función de ejecución de js:

//** Go Back interception function ------------------------------------------

    var currentScope;

    var defaultGoBack = $rootScope.$ionicGoBack;

    $rootScope.$ionicGoBack = function() {
        if ( angular.isFunction( currentScope.customGoBack ) ) {

            //assign default go back function to as a "super" function ^^
            currentScope.customGoBack.super = defaultGoBack;

            //if there is a custom back function, execute-it
            currentScope.customGoBack();

        } else {
            //else, execute default go back
            defaultGoBack();
        }
    };

    //Store targetScope to global each time the view is changing
    $rootScope.$on( '$ionicView.beforeEnter', function( event ) {
        currentScope = event.targetScope;
    });

Ahora, puede crear una función goback personalizada en controladores :

$scope.customGoBack = function() {
   console.log( "customGoBack" );
   $scope.customGoBack.super();
};

Esta función se llamará automáticamente cuando el usuario toque el botón nav-back-button.

Si quieres llamar a GoBack por ti mismo, puedes hacerlo de esta manera :

$rootScope.$ionicGoBack();

Si desea omitir la función personalizada mientras está declarada, aquí tiene:

$ionicHistory.goBack();

Puede asignar diferentes comportamiento del botón atrás directamente en cada controlador:)

 0
Author: mopi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-11-23 21:34:09

Recibió los comentarios de @raven.zuo e hizo algunas enmiendas para anular el registro del evento de cambio de estado.

(function () {
    'use strict';

    angular
        .module('appName')
        .service('customBackButtonService', customBackButtonService);

    customBackButtonService.$inject = ['$rootScope', '$ionicPlatform'];
    function customBackButtonService($rootScope, $ionicPlatform) {

        var service = {
            setup: setup
        };

        return service;

        ////////////////

        function setup(customBackFunction) {
            // override soft back
            // framework calls $rootScope.$ionicGoBack when soft back button is pressed
            $rootScope.oldSoftBack = $rootScope.$ionicGoBack;
            $rootScope.$ionicGoBack = function () {
                customBackFunction();
            };
            var deregisterSoftBack = function () {
                $rootScope.$ionicGoBack = $rootScope.oldSoftBack;
            };

            // override hard back
            // registerBackButtonAction() returns a function which can be used to deregister it
            var deregisterHardBack = $ionicPlatform.registerBackButtonAction(
                customBackFunction, 101
            );

            // cancel custom back behaviour
            var backStateChangeWatcher = $rootScope.$on('$stateChangeStart', function () {
                if($rootScope.oldSoftBack){
                    deregisterHardBack();
                    deregisterSoftBack();

                    // Un-register watcher
                    backStateChangeWatcher();
                }
            });
        }
    }
})();

//Called via:

    customBackButtonService.setup(function () {
        console.log('custom back');
    });
 0
Author: johnw86,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-03-09 14:25:05