Подтвердить что ты не робот

Ионное изменение поведения кнопки BACK для конкретного контроллера

Я хочу иметь возможность переопределить кнопку BACK на панели навигации и кнопку аппаратного обеспечения.

Я хочу, чтобы это переопределение было для одного конкретного контроллера, но не для остальных контроллеров.

  • он должен быть отменен, когда пользователь переместится на другой экран

(с использованием ионного v1.0.0 урана-единорога)


Моя причина в том, что у меня есть список предметов. При нажатии на список открывается страница с 3 вкладками. Каждая вкладка имеет один и тот же контроллер.

Однако нажатие BACK на любом из этих вкладок должно вернуться к основному списку. Вот как это работает на собственных устройствах, так что я хотел бы, чтобы он работал над моим гибридным приложением.


Многие решения, предоставляемые в Интернете, похоже, для старых бета-версий или для регистрации вне контроллеров.

Общее решение для работы с аппаратной кнопкой Android в контроллере:

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

Однако, похоже, это не работает на кнопке мягкой навигационной панели, и она работает на всех контроллерах, а не только на одном.

4b9b3361

Ответ 1

Можно переопределить обе кнопки в вашем контроллере, без каких-либо изменений HTML-кода.

Подводя итог:

  • Кнопка мягкой навигационной панели - переопределение $rootScope.$ionicGoBack()
  • Жесткая Android-кнопка - используйте $ionicPlatform.registerBackButtonAction()

Подробные пояснения ниже.


Решение для переопределения мягкой навигационной панели Кнопка BACK происходит от понимания того, что делает Ionic при нажатии этой кнопки.

Из Ionic docs для 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
  • scope будет единственным контроллером
  • поведение по умолчанию восстановлено

Следующий код иллюстрирует, как это можно сделать:

// 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 и выпускает страницы:

Ответ 2

Я взял предложение Ричарда и включил его в сервис, чтобы сделать его более многоразовым.

Контроллер

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

Ответ 3

Вы говорите о мягкой навигации, как в задней кнопке на ионной панели заголовка или ион-навигационной панели? потому что это легко исправить. Просто создайте собственную панель заголовков для этого шаблона. так что на этом шаблоне состояния просто используйте что-то вроде этого.

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

Ответ 4

Вышеупомянутый ответ на переопределение $rootScope. $ionicGoBack частично работает.

Проблема заключается в способе отмены регистрацииSoftBack. Я попробовал вышеупомянутую $scope. $On ('$ destroy', a_function), а также новую $scope. $On ('$ ionicView.beforeLeave', a_function) не работает.

Причина этого: новый контроллер будет введен до того, как будет отменен регистраторSoftBack, чтобы отменить регистратор. Поэтому я немного изменил решение, чтобы оно работало.

  • измените

    var oldSoftBack = $rootScope.$ionicGoBack
    

    to

    $rootScope.oldSoftBack = $rootScope.$ionicGoBack
    
  • deregister в $rootScope. $on ( "$ stateChangeStart", your_function), код:

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

Ответ 5

Взял обратную связь от @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');
    });

Ответ 6

это мое решение:)

Поместите эту часть кода в свою функцию запуска 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();
};

Эта функция будет автоматически вызываться, когда пользователь нажимает кнопку nav-back-button.

Если вы хотите позвонить goBack самостоятельно, вы можете сделать это следующим образом:

$rootScope.$ionicGoBack();

Если вы хотите обойти пользовательскую функцию, тогда как она объявлена, вы здесь:

$ionicHistory.goBack();

Вы можете назначить другое поведение для кнопки "Назад" непосредственно в каждом контроллере:)