如何在iOS中像Android一样实现菜单

我需要像android.menu意味着在导航上的button(右侧) iOS的菜单。

如果我点击那个菜单就会显示。

我正在使用故事板。

所以你想要这样的东西:

应用程序演示截图

即使在景观工程:

lanscape版本

我认为这将是永恒的,我要解释:D

基本上我创build了一个自定义的UINavigationController,如上面的注释中所提到的,将其称为ActionBarNavigationController

从这个自定义的UINavigationController,我添加了一个自定义的UIView显示与下拉button在右边的ActionBar

下拉菜单是一个UITableView带有您select的填充列表。

我在iOS中使用protocol来处理即使在下拉菜单中的每一行。

一切都是纯粹的代码完成的。 如果您愿意,可以将这些文件添加到您的项目中,在必要时我已经提供了完整的代码。

AppDelegate.m

 #import "AppDelegate.h" #import "ActionBarNavController.h" #import "ViewController.h" @interface AppDelegate () @end @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // Override point for customization after application launch. self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; // ---------------------------------------------------------------------- // Our custom UINavigationController will contain the // Android styled action bar as a subview as well as the // drop down list. // // You can probably set the menu list items inside each individual // controller instead of here. This is just for demo purpose. // ---------------------------------------------------------------------- ActionBarNavController *actionBarNavController = [[ActionBarNavController alloc] init]; // ---------------------------------------------------------------------- // Initialize our main view controller and add it to // action bar navigation controller. // ---------------------------------------------------------------------- ViewController *viewController = [[ViewController alloc] init]; actionBarNavController.viewControllers = @[viewController]; self.window.rootViewController = actionBarNavController; [self.window makeKeyAndVisible]; [actionBarNavController setNavTitle:@"Action Bar"]; // telling the controller the drop down list items [actionBarNavController setMenuList:@[@"Action1", @"Action2", @"Action3"]]; return YES; } 

ViewController.h

ViewController只是你的普通的UIViewController,它符合我在下面的类中创build的ActionBarNavControllerDelegate 。 确保包含它。

 #import <UIKit/UIKit.h> #import "ActionBarNavController.h" @interface ViewController : UIViewController <ActionBarNavControllerDelegate> @property (nonatomic, strong) ActionBarNavController *navController; @property (nonatomic, strong) UILabel *lblMessage; @end 

ViewController.m

 #import "ViewController.h" @interface ViewController () @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. // store the nav controller for easy access self.navController = (ActionBarNavController *)self.navigationController; self.navController.actionBarDelegate = self; [[UIApplication sharedApplication] setStatusBarHidden:NO]; [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent]; [self initViews]; [self initConstraints]; } -(void)initViews { self.view.backgroundColor = [UIColor whiteColor]; self.lblMessage = [[UILabel alloc] init]; self.lblMessage.text = @"This is your main view controller.\n\nPress the top right action bar button to see drop down menu."; self.lblMessage.font = [UIFont systemFontOfSize:20]; self.lblMessage.numberOfLines = 0; self.lblMessage.lineBreakMode = NSLineBreakByWordWrapping; self.lblMessage.textAlignment = NSTextAlignmentCenter; [self.view addSubview:self.lblMessage]; } -(void)initConstraints { self.lblMessage.translatesAutoresizingMaskIntoConstraints = NO; id views = @{ @"lblMessage": self.lblMessage }; [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-20-[lblMessage]-20-|" options:0 metrics:nil views:views]]; [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[lblMessage]|" options:0 metrics:nil views:views]]; } #pragma mark - DropDownMenu Delegate Methods - -(void)actionBarDropDownChosenItem:(NSString *)chosenItem { if([chosenItem isEqualToString:@"Action1"]) { self.lblMessage.text = @"You have chosen action 1"; } else if([chosenItem isEqualToString:@"Action2"]) { self.lblMessage.text = @"You have chosen action 2"; } else if([chosenItem isEqualToString:@"Action3"]) { self.lblMessage.text = @"You have chosen action 3"; } // hide actionBar drop down list [self.navController hideDropDownMenu]; } @end 

ActionBarNavController.h

这个ActionBarNavController包含一个ActionBar自定义视图的实例。 它处理用户在下拉button上的交互。

 #import <UIKit/UIKit.h> #import "ActionBar.h" // ------------------------------------------------------------ // Protocol is for handling when user selects an action // from the drop down list, we need to inform any conforming // delegate view controller the option was chosen. // ------------------------------------------------------------ @protocol ActionBarNavControllerDelegate <NSObject> @optional -(void)actionBarDropDownChosenItem:(NSString *)chosenItem; @end @interface ActionBarNavController : UINavigationController <UITableViewDataSource, UITableViewDelegate> // actionBar is a custom subclass that looks like Android's action bar @property (nonatomic, strong) ActionBar *actionBar; // the tableview will be our drop down list @property (nonatomic, strong) UITableView *tableView; // a boolean flag for toggling drop down menu @property (nonatomic, assign) BOOL dropDownVisible; @property (nonatomic, strong) NSArray *arrMenuItems; @property (nonatomic, weak) id<ActionBarNavControllerDelegate> actionBarDelegate; -(void)setNavTitle:(NSString *)navTitle; -(void)setMenuList:(NSArray *)menuItems; -(void)showDropDownMenu; -(void)hideDropDownMenu; @end 

ActionBarNavController.m

 #import "ActionBarNavController.h" #import "DropDownCell.h" @interface ActionBarNavController () @end @implementation ActionBarNavController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. [self initViews]; [self initConstraints]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } #pragma mark - Setup Methods - -(void)initViews { self.view.clipsToBounds = YES; // hide default navigation bar [self setNavigationBarHidden:YES animated:NO]; self.navigationBar.translucent = NO; // using our own custom looking action bar self.actionBar = [[ActionBar alloc] init]; [self.actionBar.btnMenu addTarget:self action:@selector(toggleMenu) forControlEvents:UIControlEventTouchUpInside]; // setting up drop down list using a UITableView self.tableView = [[UITableView alloc] init]; self.tableView.dataSource = self; self.tableView.delegate = self; self.tableView.alpha = 0; self.tableView.backgroundColor = [UIColor colorWithRed:0.15 green:0.15 blue:0.15 alpha:1.0]; self.tableView.rowHeight = 50; self.tableView.scrollEnabled = NO; [self.view addSubview:self.actionBar]; [self.view addSubview:self.tableView]; } -(void)initConstraints { self.actionBar.translatesAutoresizingMaskIntoConstraints = NO; self.tableView.translatesAutoresizingMaskIntoConstraints = NO; id views = @{ @"actionBar": self.actionBar, @"tableView": self.tableView }; [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[actionBar]|" options:0 metrics:nil views:views]]; [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:[tableView(200)]|" options:0 metrics:nil views:views]]; [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[actionBar(70)][tableView(150)]" options:0 metrics:nil views:views]]; } #pragma mark - Other Methods - -(void)setNavTitle:(NSString *)navTitle { self.actionBar.lblTitle.text = navTitle; [self.view layoutIfNeeded]; } -(void)setMenuList:(NSArray *)menuItems { self.arrMenuItems = menuItems; [self.tableView reloadData]; } #pragma mark - Drop Down Button Methods - -(void)toggleMenu { if(self.dropDownVisible) { self.dropDownVisible = NO; [self hideDropDownMenu]; } else { self.dropDownVisible = YES; [self showDropDownMenu]; } } -(void)showDropDownMenu { self.dropDownVisible = YES; [UIView animateWithDuration:0.15 animations:^{ self.tableView.alpha = 1.0; }]; } -(void)hideDropDownMenu { self.dropDownVisible = NO; [UIView animateWithDuration:0.15 animations:^{ self.tableView.alpha = 0.0; }]; } #pragma mark - TableView Methods - -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return self.arrMenuItems.count; } -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *cellID = @"cellID"; DropDownCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID]; if(cell == nil) { cell = [[DropDownCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellID]; } cell.lblTitle.text = self.arrMenuItems[indexPath.row]; return cell; } -(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath { // Remove seperator inset if ([cell respondsToSelector:@selector(setSeparatorInset:)]) { [cell setSeparatorInset:UIEdgeInsetsZero]; } // Prevent the cell from inheriting the Table View's margin settings if ([cell respondsToSelector:@selector(setPreservesSuperviewLayoutMargins:)]) { [cell setPreservesSuperviewLayoutMargins:NO]; } // Explictly set your cell's layout margins if ([cell respondsToSelector:@selector(setLayoutMargins:)]) { [cell setLayoutMargins:UIEdgeInsetsZero]; } } -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { if([self.actionBarDelegate respondsToSelector:@selector(actionBarDropDownChosenItem:)]) { [self.actionBarDelegate actionBarDropDownChosenItem:self.arrMenuItems[indexPath.row]]; } } @end 

ActionBar.h

这个ActionBar类是自定义的UIView用下拉button来显示操作栏。

 #import <UIKit/UIKit.h> @interface ActionBar : UIView @property (nonatomic, strong) UIView *container; @property (nonatomic, strong) UILabel *lblTitle; @property (nonatomic, strong) UIButton *btnMenu; @end 

ActionBar.m

 #import "ActionBar.h" @implementation ActionBar -(id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if(self) { [self initViews]; [self initConstraints]; } return self; } -(void)initViews { self.container = [[UIView alloc] init]; self.container.backgroundColor = [UIColor colorWithRed:0.2 green:0.2 blue:0.2 alpha:1.0]; self.lblTitle = [[UILabel alloc] init]; self.lblTitle.textColor = [UIColor whiteColor]; self.lblTitle.text = @"Title"; self.btnMenu = [[UIButton alloc] init]; [self.btnMenu setImage:[UIImage imageNamed:@"androidMenuButton"] forState:UIControlStateNormal]; [self.container addSubview:self.lblTitle]; [self.container addSubview:self.btnMenu]; [self addSubview:self.container]; } -(void)initConstraints { self.container.translatesAutoresizingMaskIntoConstraints = NO; self.lblTitle.translatesAutoresizingMaskIntoConstraints = NO; self.btnMenu.translatesAutoresizingMaskIntoConstraints = NO; id views = @{ @"container": self.container, @"lblTitle": self.lblTitle, @"btnMenu": self.btnMenu }; // container constraints [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[container]|" options:0 metrics:nil views:views]]; [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[container]|" options:0 metrics:nil views:views]]; // container subview constraints [self.container addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-10-[lblTitle]-10-[btnMenu]|" options:0 metrics:nil views:views]]; [self.container addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-20-[lblTitle]|" options:0 metrics:nil views:views]]; [self.container addConstraint:[NSLayoutConstraint constraintWithItem:self.btnMenu attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self.lblTitle attribute:NSLayoutAttributeCenterY multiplier:1.0 constant:0.0]]; } @end 

DropDownCell.h

这个自定义的UITableViewCell类控制下拉菜单单元格的外观。

 #import <UIKit/UIKit.h> @interface DropDownCell : UITableViewCell @property (nonatomic, strong) UILabel *lblTitle; @end 

DropDownCell.m

 #import "DropDownCell.h" @implementation DropDownCell -(id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; if(self) { [self initViews]; [self initConstraints]; } return self; } -(void)initViews { self.backgroundColor = [UIColor clearColor]; self.contentView.backgroundColor = [UIColor clearColor]; self.selectionStyle = UITableViewCellSelectionStyleNone; self.lblTitle = [[UILabel alloc] init]; self.lblTitle.textColor = [UIColor whiteColor]; [self.contentView addSubview:self.lblTitle]; } -(void)initConstraints { self.lblTitle.translatesAutoresizingMaskIntoConstraints = NO; id views = @{ @"lblTitle": self.lblTitle }; [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-10-[lblTitle]|" options:0 metrics:nil views:views]]; [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[lblTitle]|" options:0 metrics:nil views:views]]; } @end 

下拉图标

androidMenuButton @ 1x,@ 2x,@ 3x

1X2倍3X

我会使用Popover而不是完整的自定义菜单。 在iPhone上,build议使用全屏模式演示而不是popup式菜单,但仍然可以。

该图像来自Popover文档 。

在这里输入图像说明

有关如何执行此操作的更多详细信息,请参阅此答案 。