Tengo una app de iOS 7 donde voy a instalar una custom de nuevo el botón como este:

    UIImage *backButtonImage = [UIImage imageNamed:@"back-button"];
    UIButton *backButton = [UIButton buttonWithType:UIButtonTypeCustom];

    [backButton setImage:backButtonImage forState:UIControlStateNormal];
    backButton.frame = CGRectMake(0, 0, 20, 20);

    [backButton addTarget:self
                   action:@selector(popViewController)
         forControlEvents:UIControlEventTouchUpInside];

    UIBarButtonItem *backBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:backButton];
    viewController.navigationItem.leftBarButtonItem = backBarButtonItem;

Pero esto deshabilita el iOS 7 «desliza el dedo de izquierda a derecha de» gestos para navegar a la anterior controlador. ¿Alguien sabe cómo puedo configurar un botón personalizado y todavía mantener este gesto habilitado?

EDITAR:
He tratado de establecer el viewController.navigationItem.backBarButtonItem en su lugar, pero esto no parece mostrar mi imagen personalizada.

Todavía tengo que encontrar una solución adecuada para este problema?? Hay alguien que ha encontrado una buena solución y explicar por qué está trabajando??.
Cómo sobre el uso de la bien hecha de la biblioteca de terceros: SwipeBack?

OriginalEl autor lehn0058 | 2013-09-27

14 Comentarios

  1. 76

    IMPORTANTE:
    Este es un hack. Yo recomendaría echar un vistazo a este respuesta.

    Llamar a la línea siguiente después de asignar el leftBarButtonItem trabajado para mí:

    self.navigationController.interactivePopGestureRecognizer.delegate = self;

    Edición:
    Esto no funciona si llamada en init métodos. Debería ser llamado en viewDidLoad o métodos similares.

    ¿Que esta en el controlador de vista? o la navegación por el controlador? Tengo el mismo problema, pero este no parece el trabajo?
    Después de descargar el proyecto de ejemplo ahora entiendo tu problema. El código funciona mientras la colección de la vista del contenido no exceda el ancho horizontal de la vista controlador. Sin embargo, tan pronto como la colección de visión horizontal de desplazamiento que anula el interactivePopGestureRecognizer. Voy a ver si puedo encontrar un trabajo.
    Tengo problema con este código. Esto funciona no mucho tiempo, después de 5-10 back-golpes de VC se congela. Alguna solución?
    Timur Bernikowich me experimentando lo mismo.Encontraste alguna de las razones para esto?
    Ajuste el delegado self desactiva el de un objeto de la clase _UINavigationInteractiveTransition. Es la responsabilidad de que el objeto de garantizar que la navegación controlador no se le dice al pop, mientras que ya está en transición. Aún se investiga si es posible habilitar este gesto o no cuando el botón atrás es la costumbre.

    OriginalEl autor Paul Hunter

  2. 56

    Utilizar el backIndicatorImage y backIndicatorTransitionMaskImage propiedades de la UINavigationBar si es posible. La configuración de estos en un UIAppearanceProxy puede modificar fácilmente el comportamiento a través de su aplicación. La arruga es que sólo se puede establecer aquellos en ios 7, pero de que funciona, ya que sólo puede utilizar el pop gesto en ios 7 de todos modos. Su normal ios 6 estilo puede permanecer intacto.

    UINavigationBar* appearanceNavigationBar = [UINavigationBar appearance];
    //the appearanceProxy returns NO, so ask the class directly
    if ([[UINavigationBar class] instancesRespondToSelector:@selector(setBackIndicatorImage:)])
    {
        appearanceNavigationBar.backIndicatorImage = [UIImage imageNamed:@"back"];
        appearanceNavigationBar.backIndicatorTransitionMaskImage = [UIImage imageNamed:@"back"];
        //sets back button color
        appearanceNavigationBar.tintColor = [UIColor whiteColor];
    }else{
        //do ios 6 customization
    }

    Tratando de manipular la interactivePopGestureRecognizer del delegado llevará a un montón de problemas.

    Gracias Dan, esto es muy importante y debe ser aceptada respuesta. Simplemente re-asignar el delegado se abren a UNA gran cantidad de comportamientos extraños. Especialmente cuando los usuarios intentan pase de vuelta en el topViewController.
    Este hecho debe ser aceptada respuesta.
    Esta es una solución suponiendo que todo lo que quiero hacer es cambiar el botón atrás de la imagen. Pero lo que si desea cambiar el botón atrás de texto y/o la acción que se realiza al hacer clic en el botón atrás?
    En ese punto usted que sería mejor servido por la configuración de la UINavigationItem.leftBarButtonItem. Hay una variedad de respuestas que se pueden encontrar mediante la búsqueda leftBarButtonItem en google o en stackoverflow.
    Por desgracia, esto no funciona en iOS8. El botón atrás no cambiar su apariencia a mi imagen personalizada.

    OriginalEl autor Saltymule

  3. 28

    Vi esta solución http://keighl.com/post/ios7-interactive-pop-gesture-custom-back-button/ que las subclases UINavigationController. Su mejor solución como la que se maneja el caso de que pase antes de que el controlador está en su lugar, lo que provoca un accidente.

    Además de esto me di cuenta de que si haces un golpe en la raíz de vista controlador (después de pulsar en uno, y de vuelta otra vez) la interfaz de usuario no responde (también el mismo problema en la respuesta anterior).

    Por lo que el código en el subclases UINavigationController debe verse así:

    @implementation NavigationController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        __weak NavigationController *weakSelf = self;
    
        if ([self respondsToSelector:@selector(interactivePopGestureRecognizer)]) {
            self.interactivePopGestureRecognizer.delegate = weakSelf;
            self.delegate = weakSelf;
        }
    }
    
    - (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated {
        //Hijack the push method to disable the gesture
        if ([self respondsToSelector:@selector(interactivePopGestureRecognizer)]) {
            self.interactivePopGestureRecognizer.enabled = NO;
        }
        [super pushViewController:viewController animated:animated];
    }
    
    #pragma mark - UINavigationControllerDelegate
    
    - (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animate {
        //Enable the gesture again once the new controller is shown
        self.interactivePopGestureRecognizer.enabled = ([self respondsToSelector:@selector(interactivePopGestureRecognizer)] && [self.viewControllers count] > 1);
    }
    
    @end
    tenía los mismos problemas con deslizar en la raíz de controlador de vista, gracias!
    Funciona perfectamente, gracias!
    LA MEJOR SOLUCIÓN EN EL CONJUNTO DE LA PÁGINA. FUNCIONA PERFECTAMENTE BIEN. GRACIAS
    Esta es la respuesta correcta!

    OriginalEl autor Nick H247

  4. 19

    Yo uso

    [[UINavigationBar appearance] setBackIndicatorImage:[UIImage imageNamed:@"nav_back.png"]];
    [[UINavigationBar appearance] setBackIndicatorTransitionMaskImage:[UIImage imageNamed:@"nav_back.png"]];
    
    [UIBarButtonItem.appearance setBackButtonTitlePositionAdjustment:UIOffsetMake(0, -64) forBarMetrics:UIBarMetricsDefault];
    He visto comentarios en otra parte que esto causa problemas en el modo de 64 bits debido a un error de Apple código en la actualidad, sólo pensé que había puesto una advertencia
    ¿qué tipo de error?
    Simplemente la mejor solución!
    La solución más sencilla que nunca.
    sí, mejor. gracias !

    OriginalEl autor Albert Chu

  5. 6

    Yo también ocultar el botón atrás, reemplazándolo con una costumbre leftBarItem.

    La eliminación de interactivePopGestureRecognizer delegado después de acción de empuje trabajado para mí:

    [self.navigationController pushViewController:vcToPush animated:YES];
    
    //Enabling iOS 7 screen-edge-pan-gesture for pop action
    if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)]) {
        self.navigationController.interactivePopGestureRecognizer.delegate = nil;
    }
    Un problema con este método es que si usted realiza un borde de la cacerola en una raíz de vista es el bloqueo de la interfaz de usuario. Me encontré con esto porque estoy empujando a varias instancias de la misma vista que el nav de la pila.
    Gracias por dejarme saber! Podría usted por favor, describa la situación exacta? No podía reproducirlo al pasar la raíz de controlador de vista
    Me estaba preparando en el método viewDidLoad. Mi solución final fue para establecer otra clase de ser el delegado de la que sólo devuelve true para ‘gestureRecognizerShouldBegin’ si hay más de un controlador de vista en el nav de la pila.
    Gran solución, gracias
    MrNickBarker razones por las que se congela estoy experimentando el mismo

    OriginalEl autor avishic

  6. 6
    navigationController.interactivePopGestureRecognizer.delegate = (id<UIGestureRecognizerDelegate>)self;

    Esto es de http://stuartkhall.com/posts/ios-7-development-tips-tricks-hacks, pero hace varios errores:

    1. Empujar a otro viewController en el navigationController cuando deslice rápidamente el dedo desde el borde izquierdo de la pantalla;
    2. O, deslice el dedo rápidamente desde el borde izquierdo de la pantalla cuando el topViewController está surgiendo de la navigationController;

    por ejemplo, Cuando el rootViewController de navigationController está mostrando, deslice el dedo rápidamente desde el borde izquierdo de la pantalla y toque algo(RÁPIDAMENTE) para empujar anotherViewController en el navigationController, entonces

    • La rootViewController no responder a cualquier evento de toque;
    • La anotherViewController no se muestra;
    • Deslice el dedo desde el borde de la pantalla de nuevo, la anotherViewController se muestra;
    • Toque personalizado botón atrás para meter el anotherViewController, crash!

    Por lo que debe implementar UIGestureRecognizerDelegate método en self.navigationController.interactivePopGestureRecognizer.delegate como este:

    - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
        if (gestureRecognizer == navigationController.interactivePopGestureRecognizer) {
            return !navigationController.<#TODO: isPushAnimating#> && [navigationController.viewControllers count] > 1;
        }
        return YES;
    }
    SwipeBack es una solución para estos problemas.

    OriginalEl autor iwill

  7. 6

    Aquí es swift3 versión de Nick H247 la respuesta

    class NavigationController: UINavigationController {
      override func viewDidLoad() {
        super.viewDidLoad()
        if responds(to: #selector(getter: interactivePopGestureRecognizer)) {
          interactivePopGestureRecognizer?.delegate = self
          delegate = self
        }
      }
    
      override func pushViewController(_ viewController: UIViewController, animated: Bool) {
        if responds(to: #selector(getter: interactivePopGestureRecognizer)) {
          interactivePopGestureRecognizer?.isEnabled = false
        }
        super.pushViewController(viewController, animated: animated)
      }
    }
    
    extension NavigationController: UINavigationControllerDelegate {
      func navigationController(_ navigationController: UINavigationController, didShow viewController: UIViewController, animated: Bool) {
        interactivePopGestureRecognizer?.isEnabled = (responds(to: #selector(getter: interactivePopGestureRecognizer)) && viewControllers.count > 1)
      }
    }
    
    extension NavigationController: UIGestureRecognizerDelegate {}
    gracias por la traducción! 🙂

    OriginalEl autor duan

  8. 3

    Intentar self.navigationController.interactivePopGestureRecognizer.enabled = YES;

    No, ya está habilitado.. el problema parece ser que el delegado no permitir que el gesto de reconocimiento para empezar, he añadido mi solución como otra respuesta aquí.
    avishic podría usted por favor atender a explicar por qué establecer el delegado de trabajo?..Estoy atascado en el mismo problema.

    OriginalEl autor ilya n.

  9. 1

    Yo no escribí esto, pero el siguiente blog ha ayudado mucho y ha solucionado mis problemas con la costumbre botón de navegación:

    http://keighl.com/post/ios7-interactive-pop-gesture-custom-back-button/

    En resumen, se implementa una costumbre UINavigationController que utiliza el pop gesto delegado. Muy limpio y portátil!

    Código:

    @interface CBNavigationController : UINavigationController <UINavigationControllerDelegate, UIGestureRecognizerDelegate>
    @end
    
    @implementation CBNavigationController
    
    - (void)viewDidLoad
    {
      __weak CBNavigationController *weakSelf = self;
    
      if ([self respondsToSelector:@selector(interactivePopGestureRecognizer)])
      {
        self.interactivePopGestureRecognizer.delegate = weakSelf;
        self.delegate = weakSelf;
      }
    }
    
    //Hijack the push method to disable the gesture
    
    - (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated
    {
      if ([self respondsToSelector:@selector(interactivePopGestureRecognizer)])
        self.interactivePopGestureRecognizer.enabled = NO;
    
      [super pushViewController:viewController animated:animated];
    }
    
    #pragma mark UINavigationControllerDelegate
    
    - (void)navigationController:(UINavigationController *)navigationController
           didShowViewController:(UIViewController *)viewController
                        animated:(BOOL)animate
    {
      //Enable the gesture again once the new controller is shown
    
      if ([self respondsToSelector:@selector(interactivePopGestureRecognizer)])
        self.interactivePopGestureRecognizer.enabled = YES;
    }

    Editar. Añadido fix para los problemas cuando un usuario intenta deslizar hacia la izquierda en una raíz de controlador de vista:

    - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
    
        if ([self respondsToSelector:@selector(interactivePopGestureRecognizer)] &&
            self.topViewController == [self.viewControllers firstObject] &&
            gestureRecognizer == self.interactivePopGestureRecognizer) {
    
            return NO;
        }
    
        return YES;
    }
    IU se bloquea si uno pasa un dedo a la izquierda en la raíz de controlador de vista de la Navegación controlador.
    He editado la respuesta con una solución que creo que he implementado para resolver el problema. Ha sido un tiempo, pero tiene sentido. Básicamente, si la parte superior de la vista controlador es la raíz de controlador de vista, entonces no vamos a responder a la ‘interactivePopGestureRecognizer’
    Es ocultando mi botón atrás

    OriginalEl autor kgaidis

  10. 1

    RootView

    override func viewDidAppear(_ animated: Bool) {
        self.navigationController?.interactivePopGestureRecognizer?.isEnabled = false
    }

    ChildView

    override func viewDidLoad() {
        self.navigationController?.interactivePopGestureRecognizer?.isEnabled = true
        self.navigationController?.interactivePopGestureRecognizer?.delegate = self
    } 
    
    extension ChildViewController: UIGestureRecognizerDelegate {}

    OriginalEl autor PW486

  11. 1

    El uso de esta lógica para mantener activar o desactivar el gesto..

    - (void)navigationController:(UINavigationController *)navigationController
           didShowViewController:(UIViewController *)viewController
                        animated:(BOOL)animate
    {
        if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)])
        {
            if (self.navigationController.viewControllers.count > 1)
            {
                self.navigationController.interactivePopGestureRecognizer.enabled = YES;
            }
            else
            {
                self.navigationController.interactivePopGestureRecognizer.enabled = NO;
            }
        }
    }

    OriginalEl autor Muhammad Naeem Paracha

  12. 0

    He tenido un problema similar donde estaba la asignación de la vista actual del controlador como el delegado de la interactivos pop gesto, pero rompería el gesto en vistas empujado, o puntos de vista debajo de la vista en el nav de la pila. La forma en que lo resuelto fue establecer el delegado en -viewDidAppear, a continuación, establezca a nil en -viewWillDisappear. Que permitió que mis otros puntos de vista para que funcione correctamente.

    OriginalEl autor Bill Burgess

  13. 0

    Imaginamos que estamos usando Apple por defecto del maestro/detalle de la plantilla de proyecto, en la que la maestra es una vista de tabla controlador y pulsando en él se mostrará el detalle de controlador de vista.

    Queremos personalizar el botón que aparece en la vista de detalles del controlador. Esto es cómo personalizar la imagen, el color de la imagen, texto, color de texto, y fuente del botón atrás.


    Para cambiar la imagen, el color de la imagen, el color del texto o la fuente a nivel mundial, coloque la siguiente en un lugar que se llama antes de que su punto de vista de los controladores se crean (por ejemplo, application:didFinishLaunchingWithOptions: es un buen lugar).

    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
        UINavigationBar* navigationBarAppearance = [UINavigationBar appearance];
    
        //change the back button, using default tint color
        navigationBarAppearance.backIndicatorImage = [UIImage imageNamed:@"back"];
        navigationBarAppearance.backIndicatorTransitionMaskImage = [UIImage imageNamed:@"back"];
    
        //change the back button, using the color inside the original image
        navigationBarAppearance.backIndicatorImage = [[UIImage imageNamed:@"back"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
        navigationBarAppearance.backIndicatorTransitionMaskImage = [UIImage imageNamed:@"back"];
    
        //change the tint color of everything in a navigation bar
        navigationBarAppearance.tintColor = [UIColor greenColor];
    
        //change the font in all toolbar buttons
        NSDictionary *barButtonTitleTextAttributes =
        @{
          NSFontAttributeName: [UIFont fontWithName:@"HelveticaNeue-Light" size:12.0],
          NSForegroundColorAttributeName: [UIColor purpleColor]
          };
    
        [[UIBarButtonItem appearance] setTitleTextAttributes:barButtonTitleTextAttributes forState:UIControlStateNormal];
    
        return YES;
    }

    Nota, puede utilizar appearanceWhenContainedIn: a tener más control sobre la visión que los controladores son afectados por estos cambios, pero tenga en cuenta que usted no puede pasar [DetailViewController class], porque se encuentra dentro de un UINavigationController, no su DetailViewController. Esto significa que usted tendrá subclase UINavigationController si desea más control sobre lo que se ve afectado.

    Para personalizar el texto o la fuente/color de un determinado botón atrás elemento, debe hacerlo en el MasterViewController (no la DetailViewController!). Esto parece poco intuitivo porque el botón aparece en la DetailViewController. Sin embargo una vez que usted entiende que la manera de personalizar es mediante el establecimiento de una propiedad en un navigationItem, comienza a tener más sentido.

    - (void)viewDidLoad { //MASTER view controller
        [super viewDidLoad];
    
        UIBarButtonItem *buttonItem = [[UIBarButtonItem alloc] initWithTitle:@"Testing"
                                                                       style:UIBarButtonItemStylePlain
                                                                      target:nil
                                                                      action:nil];
        NSDictionary *barButtonTitleTextAttributes =
        @{
          NSFontAttributeName: [UIFont fontWithName:@"HelveticaNeue-Light" size:12.0],
          NSForegroundColorAttributeName: [UIColor purpleColor]
          };
        [buttonItem setTitleTextAttributes:barButtonTitleTextAttributes forState:UIControlStateNormal];
        self.navigationItem.backBarButtonItem = buttonItem;
    }

    Nota: al intentar establecer la titleTextAttributes después de la configuración de auto.navigationItem.backBarButtonItem no parece funcionar, por lo que se deben configurar antes de asignar el valor a esta propiedad.

    OriginalEl autor Senseful

  14. 0

    Crear una clase ‘TTNavigationViewController’, que es subclase de ‘UINavigationController’ y hacer que su navegación existente controlador de esta clase, ya sea en el guión gráfico o la clase, el código de Ejemplo en clase –

        class TTNavigationViewController: UINavigationController, UIGestureRecognizerDelegate {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        self.setNavigationBarHidden(true, animated: false)
    
        //enable slide-back
        if self.responds(to: #selector(getter: UINavigationController.interactivePopGestureRecognizer)) {
            self.interactivePopGestureRecognizer?.isEnabled = true
            self.interactivePopGestureRecognizer?.delegate  = self
        }
    }
    
    func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
        return true
    }}

    OriginalEl autor Prakash Raj

Dejar respuesta

Please enter your comment!
Please enter your name here