首页 文章

Ionic覆盖特定控制器的所有BACK按钮行为

提问于
浏览
22

我希望能够覆盖导航栏上的BACK按钮和硬件按钮 .

我希望这个覆盖是针对一个特定的控制器,而不是其他控制器 .

  • 当用户移动到另一个屏幕时必须取消它

(使用离子v1.0.0铀 - 独角兽)


我的理由是我有一个项目清单 . 单击列表将打开一个详细信息页面,其中包含3个选项卡 . 每个选项卡共享同一个控制器 .

但是,在任何这些选项卡上按BACK必须返回主列表 . 这就是它在本机设备上的工作方式,所以我希望它能够在我的混合应用程序上运行 .


在线提供的许多解决方案似乎适用于较旧的beta版本,或用于控制器之外的注册 .

在控制器内使用Android硬件按钮的常见解决方案是:

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

然而,这似乎不适用于软导航栏按钮,它适用于所有控制器,而不仅仅是一个控制器 .

6 回答

  • 61

    It is possible to override both buttons in your controller ,没有对HTML代码进行任何更改 .

    总结一下:

    • 软导航栏按钮 - 覆盖 $rootScope.$ionicGoBack()

    • 硬Android按钮 - 使用 $ionicPlatform.registerBackButtonAction()

    详细解释如下 .


    overriding the soft navigation bar BACK button 的解决方案来自于了解按下该按钮后Ionic的作用 .

    Ionic docs for ion-nav-back-button,我们已经知道:

    点击/点击时按钮自动设置为$ ionicGoBack() .

    在ionic.bundle.js中搜索源代码可以揭示如何声明:

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

    在您自己的控制器中覆盖它很简单 . 确保将 $rootScope 传递给控制器,然后修改上面的代码 . grab 指向原始函数的指针是个好主意,以便在需要时可以恢复它,或者在完成自定义处理后调用它 .

    // 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();
    };
    

    对于一个控制器, overriding the Android hardware BACK button 的解决方案来自 registerBackButtonAction() 函数的返回值,该函数执行覆盖的注销 .

    $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();
    });
    

    更多细节在这里:


    完整的解决方案需要以下内容:

    • 覆盖软导航栏BACK按钮

    • 覆盖Android硬BACK按钮

    • 范围将是单个控制器

    • 恢复了默认行为

    以下代码说明了如何完成此操作:

    // 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();
    });
    

    此问题已在Ionic论坛和问题页面上讨论过:

  • 6

    我接受了理查德的建议,并将其投入服务,使其更具可重用性 .

    The Controller

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

    The Service

    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;
    });
    
  • 0

    您是在谈论离线 Headers 栏或离子导航条上的后退按钮中的软导航?因为这是一个简单的解决方案 . 只需为该模板创建自己的自定义 Headers 栏 . 那么状态模板只是使用这样的东西 .

    <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

    以上回答覆盖$ rootScope . $ ionicGoBack部分有效 .

    问题在于deregisterSoftBack的方式 . 我尝试了上面提到的$ scope . $ on('$ destroy',a_function)以及新的$ scope . $ on('$ ionicView.beforeLeave',a_function),都不起作用 .

    原因是:新的控制器将在deregisterSoftBack之前输入,从而使取消注册失败 . 所以我稍微修改了解决方案以使其工作 .

    • 改变了
    var oldSoftBack = $rootScope.$ionicGoBack
    

    $rootScope.oldSoftBack = $rootScope.$ionicGoBack
    
    • 取消注册$ rootScope . $ on(“$ stateChangeStart”,your_function),代码为:
    if ($rootScope.oldSoftBack) {
        $rootScope.$ionicGoBack = $rootScope.oldSoftBack;
        $rootScope.oldSoftBack = null;
    }
    
  • 1

    这是我的解决方案:)

    将这部分代码放在app.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;
        });
    

    现在,您可以在控制器中创建自定义goback功能:

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

    当用户点击导航后退按钮时,将自动调用此功能 .

    如果你想自己打电话给goBack,可以这样做:

    $rootScope.$ionicGoBack();
    

    如果你想绕过自定义函数而声明它,你可以去:

    $ionicHistory.goBack();
    

    您可以直接在每个控制器中为后退按钮分配不同的行为:)

  • 0

    从@ raven.zuo那里得到反馈并做了一些修改以取消注册状态变化事件 .

    (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');
        });
    

相关问题