开发像Facebook的新iOS应用程序中的侧边菜单的最佳方法是什么?

时间:2011-11-03 00:34:44

标签: objective-c ios cocoa-touch

侧面滑动菜单似乎正在成为一种更常见的界面元素,因为更多信息被塞进每个iPhone应用程序中。 Facebook已将其纳入最新版本the new Gmail app appears to include it as well。我想知道是否有人想到最有效的方式来开发这样的东西,因为它正在成为一个更常见的界面元素。虽然我对如何构建这个有自己的想法,但我很想知道其他人的想法。

Facebook swipe navigation

18 个答案:

答案 0 :(得分:84)

Tom Adriaenssen有一个很棒的图书馆:Inferis/ViewDeck

它非常易于使用并且具有相当大的追随者。

修改

对于更轻量级的内容,请查看:mutualmobile/MMDrawerController

它没有ViewDeck的所有功能,但更容易修改和扩展。

答案 1 :(得分:48)

我为此创建了一个库。它被称为MFSideMenu

其中包括支持iphone + ipad,纵向+横向,左侧或右侧菜单,UITabBarController和平移手势。

答案 2 :(得分:34)

我最近遇到过这个,实际上并未查看代码或测试控件,但看起来它可能是一个非常不错的起点。

jtrevealsidebar

编辑: 读者还应该看看其他答案:)

答案 3 :(得分:29)

查看MMD​​rawerController:

MMDrawerController

我们无法找到我们喜欢的图书馆,所以我们只是推出了自己的图书馆。

答案 4 :(得分:12)

关键想法您必须设置self.navigationController.view的框架或中心。您必须处理两个事件。 (1) barButtonItem按。 (2)因强行滑动而导致平移手势

您可以将视图控制器发送到后台,如下所示:

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

答案 5 :(得分:11)

Facebook的实施在UINavigationBar上放置了一个UIPanGestureRecognizer。因此允许在需要的地方进行滑动。

允许执行以下操作:直接识别x / z中的触摸方向以及它们发生的速度。

此外,对UIViews进行修补(一次在屏幕上不止一个显然不同的任务 - >因此不同的控制器)应该(我很想说必须)使用iOS新的ViewController-Containment功能。没有它的每一个实现都是不好的,因为它以一种非Apple意图的方式来修改视图层次结构。

旁注:如果您对如何尽可能接近Facebook的方式感到好奇,请查看我在Github PKRevealController上开源的项目。

答案 6 :(得分:11)

更好的是 JASidePanels 。易于实施,适用于iPhone和iPad。

Github链接:JASidePanels

答案 7 :(得分:8)

开发人员已经创建了数十个不同的库来实现iOS应用的Facebook / Path风格导航。我可以列出所有这些,但是当你要求最好的一个时,这是我用来实现侧滑动导航菜单的两个选择:

1)ECSlidingViewController 它也非常容易实现和使用Storyboard。我没有遇到任何问题,也没有收到任何错误或类似的错误。我提供的链接几乎都有解释才能使用它。

2)SWRevealViewController 这个库很容易使用,你可以找到一个教程HERE,它展示了如何使用所有解释和图像来实现它。您可以按照教程进行操作,稍后再次感谢我。

答案 8 :(得分:7)

另一种选择是使用Scringo。它为您提供了类似youtube / facebook应用程序的侧边菜单,以及菜单中您可以选择添加的所有内置功能(例如聊天,邀请朋友等等)。

添加侧边菜单只需调用[ScringoAgent startSession ...],所有配置都可以在网站上完成。

答案 9 :(得分:4)

参考这里,一个非常好的起点: slide out navigation like facebook and path

答案 10 :(得分:4)

这个问题很受欢迎,但这一切都归结为易于导入和使用......我使用的是...... SWRevealController

我很惊讶人们想念它......真的很棒!!!而且易于使用。开发人员甚至包括一些示例项目,可以让您了解如何在不同的场景中使用它。

答案 11 :(得分:3)

答案 12 :(得分:2)

Gmail和Facebook都大量使用网页浏览量,因此很难说出什么是本机代码以及HTML呈现的内容。但是,看看界面,看起来他们放置了一个UITableView,其宽度比包含他们想要显示的内容的UIView下面的屏幕宽度(320pt)窄。选择不同的tableview行可能会换出内容视图的子视图。

至少,这就是我解决问题的方法。它很难决定应该是什么。直接跳进去开始试验!

答案 13 :(得分:1)

右侧的视图可以位于UIScrollView的子类中。在此子类中,只有当用户触摸子视图时,您才可以覆盖- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event以返回YES。这样,您可以将透明的UIScrollView放在任何其他视图上,并通过子视图外发生的任何触摸事件;你可以免费获得滚动内容。

例如:

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

或:

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

答案 14 :(得分:1)

这正是facebook边栏的克隆: GHSidebarNav library

非常容易使用。指示在

答案 15 :(得分:1)

如果你想我在github GSSlideMenu做了这个回购 它允许你创建一个Facebook风格的菜单但是带有“后退”webView(通常我发现所有的回购都有一个tableView作为“后面”视图)。

答案 16 :(得分:1)

尝试在主视图下方添加您的菜单(您可以滑动到达)。开始订阅视图中的触摸事件。

实施touchesMoved:,并检查第一个gesture是否垂直(如果需要,滚动主视图)或水平(此处您需要显示菜单)。如果它是水平的,则在调用- (void)scrollAwayMainView:(NSUInteger)pixels时开始调用另一个方法touchesMoved:,计算主视图应该离开起点的像素数,并将该数字传递给方法。在该方法实现中,运行以下代码:

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

答案 17 :(得分:0)

查看我的解决方案:

How to create custom slide menu without third party library.?

您只需要子类化并填写内容的单个类。

这是班级。有关详细信息,请参阅上面的链接。

#import <UIKit/UIKit.h>

@interface IS_SlideMenu_View : UIView <UIGestureRecognizerDelegate>
{
    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