¿Cuál es la mejor manera de desarrollar un menú lateral como el de la nueva aplicación iOS de Facebook?

Parece que los menús de deslizamiento lateral se están convirtiendo en un elemento de interfaz más común a medida que se amontona más información en cada aplicación de iPhone. Facebook lo ha incluido en su última versión y la nueva aplicación de Gmail parece incluirlo también . Me preguntaba si alguien tenía ideas sobre la forma más eficiente de desarrollar algo como esto, ya que se está convirtiendo en un elemento de interfaz más común. Si bien tengo mis propios pensamientos sobre cómo construir esto, tengo curiosidad por escuchar lo que otras personas piensan.

Navegación por deslizamiento de Facebook

Hace poco me encontré con esto, en realidad no miré el código ni probé el control, pero parece que puede ser un punto de partida muy decente.

jtrevealsidebar

Editar: El lector también debe echar un vistazo a las otras respuestas 🙂

Hay una gran biblioteca para esto por Tom Adriaenssen: Inferis / ViewDeck

Es muy fácil de usar y tiene muchos seguidores.

EDITAR:

Para algo un poco más ligero, echa un vistazo a: mutualmobile / MMDrawerController

No tiene todas las características de ViewDeck, pero es más fácil de modificar y ampliar.

Creé una biblioteca para esto. Se llama MFSideMenu .

Entre otras cosas, incluye soporte para iphone + ipad, portrait + landscape, menú en el lado izquierdo o derecho, UITabBarController, y gestos panorámicos.

Mira MMDrawerController:

MMDrawerController

No pudimos encontrar la biblioteca que nos gustaba, así que hicimos la nuestra.

La idea clave es que debes establecer el marco o centro de self.navigationController.view . Hay dos eventos que debes manejar. (1) barButtonItem presione . (2) gesto de desplazamiento debido a deslizar.

Puede enviar el controlador de vista al fondo de esta manera:

[self.view sendSubviewToBack:menuViewController.view]; - (void)viewDidLoad { [super viewDidLoad]; UIBarButtonItem *barButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(buttonPressed:)]; UIPanGestureRecognizer *panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePan:)]; [self.navigationController.view addGestureRecognizer:panGestureRecognizer]; self.navigationItem.leftBarButtonItem = barButtonItem; } - (void)buttonPressed:(id)sender { CGRect destination = self.navigationController.view.frame; if (destination.origin.x > 0) { destination.origin.x = 0; } else { destination.origin.x = 320; } [UIView animateWithDuration:0.25 animations:^{ self.navigationController.view.frame = destination; }]; } - (void)handlePan:(UIPanGestureRecognizer *)recognizer { static CGPoint originalCenter; if (recognizer.state == UIGestureRecognizerStateBegan) { originalCenter = recognizer.view.center; } else if (recognizer.state == UIGestureRecognizerStateChanged) { CGPoint translation = [recognizer translationInView:self.view]; recognizer.view.center = CGPointMake(originalCenter.x + translation.x, originalCenter.y); } else if (recognizer.state == UIGestureRecognizerStateEnded || recognizer.state == UIGestureRecognizerStateCancelled || recognizer.state == UIGestureRecognizerStateFailed) { if (recognizer.view.frame.origin.x < 160) { [UIView animateWithDuration:0.25 animations:^{ recognizer.view.center = CGPointMake(384, 487.5); }]; } else { [UIView animateWithDuration:0.25 animations:^{ recognizer.view.center = CGPointMake(384 + 320, 487.5); }]; } } } 

Aún mejor es JASidePanels . Implementado fácilmente y funciona tanto para iPhone como para iPad.

Enlace de Github: JASidePanels

La implementación de Facebook coloca un UIPanGestureRecognizer en UINavigationBar. Permitiendo atrapar golpes donde sea necesario.

Eso permite hacer cosas como, reconocer la dirección táctil en x / z directamente, así como la velocidad con la que ocurrieron.

También ese tipo de retoques con UIViews (más de uno en pantalla a la vez con tareas evidentemente diferentes -> por lo tanto diferentes controladores) debería (estoy tentado de decir que debe) utilizar las nuevas características ViewController-Containment de iOS. Cada implementación sin eso es simplemente mala ya que juega con la jerarquía de vista de una manera no prevista por Apple.

En una nota al margen: si tiene mucha curiosidad sobre cómo se puede hacer lo más cerca posible de Facebook, vea el proyecto que abro en Github PKRevealController .

Existen decenas de bibliotecas diferentes que los desarrolladores han creado para implementar el estilo de navegación de Facebook / Path para las aplicaciones de iOS. Puedo enumerarlos a todos, pero como ha pedido el mejor, estas son mis dos opciones que utilizo para implementar el menú de navegación lateral:

1) ECSlidingViewController Es muy fácil de implementar y usar Storyboards también. No he tenido problemas para implementarlo ni recibí ningún error ni nada de eso. El enlace que proporcioné contiene prácticamente toda la explicación para usarlo.

2) SWRevealViewController Esta biblioteca es fácil de usar y puede encontrar un tutorial AQUÍ , que muestra cómo implementarlo con toda la explicación junto con las imágenes. Puedes seguir el tutorial y agradecerme más tarde.

Otra opción es usar Scringo . Le ofrece un menú lateral como en las aplicaciones de youtube / facebook, y también todo tipo de características incorporadas en el menú que puede elegir agregar (por ejemplo, chatear, invitar amigos, etc.)

Agregar el menú lateral es simplemente llamando a [ScringoAgent startSession …] y toda la configuración se puede hacer en el sitio.

Consulte aquí, un muy buen punto de partida: deslice hacia afuera la navegación como Facebook y la ruta

Esta pregunta es bastante popular, pero todo se redujo a una fácil importación y uso para mí … Esto es lo que uso … SWRevealController .

Me sorprende que la gente lo pierda … ¡¡¡Realmente es genial !!! y fácil de usar El desarrollador incluso incluye algunos ejemplos de proyectos que le permiten ver cómo usarlo en diferentes escenarios.

Una excelente guía sobre cómo desarrollar su propio Slide-Out-Navigation en Swift y Objective-C.

C objective

Rápido

Tanto Gmail como Facebook hacen un uso intensivo de las vistas web, por lo que es difícil decir qué es código nativo y qué es HTML. Sin embargo, mirando la interfaz, parece que han colocado una UITableView con un ancho más estrecho que el ancho de la pantalla (320pt) debajo de una UIView que contiene el contenido que desean mostrar. La selección de diferentes filas de tablas probablemente permuta una subvista de la vista de contenido.

Al menos, así es como abordaría el problema. Es difícil dictar lo que debería ser. ¡Solo súbete y comienza a experimentar!

Si quieres, hice este repository en github GSSlideMenu. Te permite crear un menú de estilo de Facebook PERO con un “atrás” webView (generalmente todos los repos que he encontrado tienen un tableView como la vista “de atrás”).

esta es exactamente la clonación de la barra lateral de Facebook: biblioteca GHSidebarNav

muy fácil de usar instrucción están en

la vista de la derecha podría estar dentro de una subclase de UIScrollView. En esta subclase, puede anular el punto - (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event para devolver SÍ únicamente si el usuario tocó la subvista. De esta forma puede colocar su UIScrollView transparente sobre cualquier otra vista y pasar por cualquier evento táctil que tenga lugar fuera de la subvista; y obtienes cosas de pergamino gratis.

Por ejemplo:

 - (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event{ CGPoint location=[self convertPoint:point toView:subview]; return (location.x > 0 && location.x < subview.frame.size.width && location.y > 0 && location.y < subview.frame.size.height); } 

o:

 - (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event{ return [subview pointInside: [self convertPoint:point toView:subview] withEvent:event]; 

Intenta agregar tu menú (al que deslizas para llegar) debajo de la vista principal. Comienza a suscribirte para tocar eventos en la vista.

Implemente touchesMoved: y compruebe si el primer gesture es vertical (desplazarse por la vista principal, si es necesario) u horizontal (aquí le gustaría mostrar el menú). Si es horizontal, comience a invocar otro método, - (void)scrollAwayMainView:(NSUInteger)pixels , siempre touchesMoved: se llama, calcula el número de píxeles desde el punto de partida de la vista principal y pasa ese número al método. En esa implementación de métodos, ejecute el siguiente código:

 [mainView scrollRectToVisible:CGRectMake:(pixels, mainView.origin.y, mainView.size.width, mainView.size.height]; 

Mira mi solución para esta pregunta:

Cómo crear un menú de diapositivas personalizado sin una biblioteca de terceros.

Una sola clase que solo necesita subclasificar y completar con contenido.

Aquí está la clase. Para más detalles, mira el enlace de arriba.

 #import  @interface IS_SlideMenu_View : UIView  { UIView* transparentBgView; BOOL hidden; int lastOrientation; } @property (strong, nonatomic) UIView *menuContainerV; + (id)sharedInstance; - (BOOL)isShown; - (void)hideSlideMenu; - (void)showSlideMenu; @end #import "IS_SlideMenu_View.h" @implementation IS_SlideMenu_View + (id)sharedInstance { static id _sharedInstance = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ _sharedInstance = [[[self class] alloc] init]; }); return _sharedInstance; } - (instancetype)initWithFrame:(CGRect)frame { frame = [[[UIApplication sharedApplication] delegate] window].frame; self = [super initWithFrame:frame]; if (self) { self.backgroundColor = [UIColor clearColor]; transparentBgView = [[UIView alloc] initWithFrame:frame]; [transparentBgView setBackgroundColor:[UIColor colorWithRed:0 green:0 blue:0 alpha:0.6]]; [transparentBgView setAlpha:0]; transparentBgView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(gestureRecognized:)]; UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(gestureRecognized:)]; [transparentBgView addGestureRecognizer:tap]; [transparentBgView addGestureRecognizer:pan]; [self addSubview:transparentBgView]; frame.size.width = 280; self.menuContainerV = [[UIView alloc] initWithFrame:frame]; CALayer *l = self.menuContainerV.layer; l.shadowColor = [UIColor blackColor].CGColor; l.shadowOffset = CGSizeMake(10, 0); l.shadowOpacity = 1; l.masksToBounds = NO; l.shadowRadius = 10; self.menuContainerV.autoresizingMask = UIViewAutoresizingFlexibleHeight; [self addSubview: self.menuContainerV]; hidden = YES; } //----- SETUP DEVICE ORIENTATION CHANGE NOTIFICATION ----- UIDevice *device = [UIDevice currentDevice]; [device beginGeneratingDeviceOrientationNotifications]; NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; [nc addObserver:self selector:@selector(orientationChanged:) name:UIDeviceOrientationDidChangeNotification object:device]; lastOrientation = [[UIDevice currentDevice] orientation]; return self; } //********** ORIENTATION CHANGED ********** - (void)orientationChanged:(NSNotification *)note { UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation]; if(orientation == UIDeviceOrientationPortrait || orientation == UIDeviceOrientationLandscapeLeft || orientation == UIDeviceOrientationLandscapeRight){ NSLog(@"%ld",orientation); if(!hidden && lastOrientation != orientation){ [self hideSlideMenu]; hidden = YES; lastOrientation = orientation; } } } - (void)showSlideMenu { UIWindow* window = [[[UIApplication sharedApplication] delegate] window]; self.frame = CGRectMake(0, 0, window.frame.size.width, window.frame.size.height); [self.menuContainerV setTransform:CGAffineTransformMakeTranslation(-window.frame.size.width, 0)]; [window addSubview:self]; // [[UIApplication sharedApplication] setStatusBarHidden:YES]; [UIView animateWithDuration:0.5 animations:^{ [self.menuContainerV setTransform:CGAffineTransformIdentity]; [transparentBgView setAlpha:1]; } completion:^(BOOL finished) { NSLog(@"Show complete!"); hidden = NO; }]; } - (void)gestureRecognized:(UIGestureRecognizer *)recognizer { if ([recognizer isKindOfClass:[UITapGestureRecognizer class]]) { [self hideSlideMenu]; } else if ([recognizer isKindOfClass:[UIPanGestureRecognizer class]]) { static CGFloat startX; if (recognizer.state == UIGestureRecognizerStateBegan) { startX = [recognizer locationInView:self.window].x; } else if (recognizer.state == UIGestureRecognizerStateChanged) { CGFloat touchLocX = [recognizer locationInView:self.window].x; if (touchLocX < startX) { [self.menuContainerV setTransform:CGAffineTransformMakeTranslation(touchLocX - startX, 0)]; } } else if (recognizer.state == UIGestureRecognizerStateEnded) { [self hideSlideMenu]; } } } - (void)hideSlideMenu { UIWindow* window = [[[UIApplication sharedApplication] delegate] window]; window.backgroundColor = [UIColor clearColor]; [UIView animateWithDuration:0.5 animations:^{ [self.menuContainerV setTransform:CGAffineTransformMakeTranslation(-self.window.frame.size.width, 0)]; [transparentBgView setAlpha:0]; } completion:^(BOOL finished) { [self removeFromSuperview]; [self.menuContainerV setTransform:CGAffineTransformIdentity]; // [[UIApplication sharedApplication] setStatusBarHidden:NO]; hidden = YES; NSLog(@"Hide complete!"); }]; } - (BOOL)isShown { return !hidden; } @end