侧面滑动菜单似乎正在成为一种更常见的界面元素,因为更多信息被塞进每个iPhone应用程序中。 Facebook已将其纳入最新版本the new Gmail app appears to include it as well。我想知道是否有人想到最有效的方式来开发这样的东西,因为它正在成为一个更常见的界面元素。虽然我对如何构建这个有自己的想法,但我很想知道其他人的想法。
答案 0 :(得分:84)
Tom Adriaenssen有一个很棒的图书馆:Inferis/ViewDeck
它非常易于使用并且具有相当大的追随者。
修改强>
对于更轻量级的内容,请查看:mutualmobile/MMDrawerController
它没有ViewDeck的所有功能,但更容易修改和扩展。
答案 1 :(得分:48)
我为此创建了一个库。它被称为MFSideMenu。
其中包括支持iphone + ipad,纵向+横向,左侧或右侧菜单,UITabBarController和平移手势。
答案 2 :(得分:34)
答案 3 :(得分:29)
答案 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)
如何在Swift和Objective-C中开发自己的滑出导航的优秀指南。
<强>目标C 强>
<强>夫特强>
答案 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