似乎随着更多信息充斥于每个iPhone应用程序中,侧滑菜单正成为一种更为常见的界面元素。Facebook已将其包含在最新版本中,而新的Gmail应用程序似乎也包含了它。我想知道是否有人想到开发这样的东西的最有效方法,因为它正在变得越来越普遍。尽管我对如何构建它有自己的想法,但我很想听听其他人的想法。
似乎随着更多信息充斥于每个iPhone应用程序中,侧滑菜单正成为一种更为常见的界面元素。Facebook已将其包含在最新版本中,而新的Gmail应用程序似乎也包含了它。我想知道是否有人想到开发这样的东西的最有效方法,因为它正在变得越来越普遍。尽管我对如何构建它有自己的想法,但我很想听听其他人的想法。
Answers:
汤姆· 阿德里亚森(Tom Adriaenssen)为此提供了一个很棒的图书馆:Inferis / ViewDeck
它非常易于使用,并且拥有大量的追随者。
编辑:
有关更轻量的内容,请查看:commonmobile / MMDrawerController
它不具有ViewDeck的所有功能,但更易于修改和扩展。
我为此创建了一个库。它称为MFSideMenu。
除其他功能外,它还包括对iphone + ipad,纵向+横向,左侧或右侧菜单,UITabBarController以及平移手势的支持。
您必须设置self.navigationController.view的frame或center的关键思想。有两个事件,你必须处理。(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);
}];
}
}
}
更好的是JASidePanels。易于实施,并且适用于iPhone和iPad。
Github链接:JASidePanels
Facebook的实现将UIPanGestureRecognizer放在UINavigationBar上。因此可以在需要的地方捕捉滑动。
这样就可以进行诸如以x / z直接识别触摸方向及其发生速度的操作。
同样,这种对UIView的修改(一次在屏幕上显示多个任务,显然任务不同->因此控制器也不同)应该(我很想说必须)使用iOS新的ViewController-Containment功能。没有它的每个实现都是很糟糕的,因为它以苹果不想要的方式修改视图层次结构。
旁注:如果您真的对如何尽可能接近Facebook的方式感到好奇,请查看我在Github PKRevealController上开源的项目。
开发人员创建了数十种不同的库来为iOS应用实现Facebook / Path样式导航。我可以列出所有这些,但是正如您要求的最好的一样,这是我用来实现侧向滑动导航菜单的两个选择:
1)ECSlidingViewController 它也非常容易实现和使用Storyboard。我没有实现它的任何问题,也没有收到任何错误或类似的东西。我提供的链接具有使用它的几乎所有解释。
2)SWRevealViewController 该库易于使用,您可以在此处找到教程,其中显示了如何实现所有说明以及图像。您可以按照本教程进行操作,稍后再谢谢。
请参阅此处,这是一个很好的起点: 滑出Facebook和path之类的导航
这个问题很受欢迎,但是全部归结为易于导入并为我使用...这是我使用的... SWRevealController。
我很惊讶人们错过了它……真的很棒!!!且易于使用。开发人员甚至包括一些示例项目,使您可以查看如何在不同的情况下使用它。
关于如何在Swift和Objective-C中开发自己的Slide-Out-Navigation的极佳指南。
目标C
迅速
Gmail和Facebook都大量使用Web视图,因此很难说出什么是本机代码,什么是呈现的HTML。但是,看一下界面,看起来他们放置了一个UITableView,其宽度比包含要显示内容的UIView的屏幕宽度(320pt)窄。选择不同的表视图行可能会换出内容视图的子视图。
至少,这就是我解决问题的方式。很难决定应该是什么。只要跳进去开始实验!
如果您想在github上执行此仓库GSSlideMenu, 它允许您使用“后” webView创建Facebook风格的菜单BUT(通常,我发现的所有仓库都具有tableView作为“后”视图)。
这正是facebook侧边栏的克隆: GHSidebarNav库
非常好用。指令在
右边的视图可能在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];
尝试在主视图下添加菜单(滑动即可进入)。开始订阅以触摸视图中的事件。
实施touchesMoved:
,并检查第一个gesture
是垂直的(如果需要,滚动主视图)还是水平的(这里要显示菜单)。如果它是水平的,则开始调用另一个方法,- (void)scrollAwayMainView:(NSUInteger)pixels
每当touchesMoved:
被调用时,计算离开主视图应起点的像素数,然后将该数字传递给该方法。在该方法的实现中,运行以下代码:
[mainView scrollRectToVisible:CGRectMake:(pixels,
mainView.origin.y,
mainView.size.width,
mainView.size.height];
查看我针对此问题的解决方案:
您只需要对其中的一个子类进行子类化并填写内容即可。
这是课程。有关更多详细信息,请参见上面的链接。
#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