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

时间:2015-08-26 16:17:03

标签: ionic-framework ionic

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

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

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

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

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

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

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

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

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

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

7 个答案:

答案 0 :(得分:61)

可以覆盖控制器中的两个按钮,而无需更改HTML代码。

总结:

  • 软导航栏按钮 - 覆盖$rootScope.$ionicGoBack()
  • 硬Android按钮 - 使用$ionicPlatform.registerBackButtonAction()

以下详细说明。

覆盖软导航栏BACK按钮的解决方案来自于了解按下该按钮后Ionic的功能。

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

  

点击/点按时,该按钮会自动设为$ionicGoBack()

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

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

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

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

仅针对一个控制器的覆盖Android硬件BACK按钮的解决方案来自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论坛上讨论过。问题页面:

答案 1 :(得分:6)

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

控制器

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

服务

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

答案 2 :(得分:2)

您是在谈论离线标题栏或离子导航栏上的后退按钮中的软导航?因为这很容易解决。只需为该模板创建自己的自定义标题栏。所以在那个状态模板上只使用这样的东西。

<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>

答案 3 :(得分:1)

以上覆盖$ rootScope的答案。$ ionicGoBack部分有效。

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

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

  1. 更改

    var oldSoftBack = $rootScope.$ionicGoBack
    

    $rootScope.oldSoftBack = $rootScope.$ionicGoBack
    
  2. 取消注册$ rootScope。$ on(“$ stateChangeStart”,your_function),代码为:

    if ($rootScope.oldSoftBack) {
        $rootScope.$ionicGoBack = $rootScope.oldSoftBack;
        $rootScope.oldSoftBack = null;
    }
    

答案 4 :(得分: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');
    });

答案 5 :(得分:0)

这是我的解决方案:)

将这部分代码放在你的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();

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

答案 6 :(得分:0)

对于那些使用最新版本的电容器和离子的人来说,这是有效的:

import { Capacitor } from "@capacitor/core";
import { App as CapacitorApp } from "@capacitor/app";

const App: React.FC = () => {
  const history = useHistory();
  useEffect(() => {
    if (Capacitor.isNativePlatform()) {
      CapacitorApp.addListener("backButton", () => {
        history.goBack();
      });
    }
  });

  return (
    <IonApp>...