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

标签 ios menu xcode6 uinavigationbar

我需要为 iOS 实现菜单,例如 android.menu 表示导航栏 bar(右侧) 上的按钮。

如果我单击,将显示该菜单。

我正在使用 Storyboard。

最佳答案

所以你想要这样的东西:

app demo screenshots

甚至在风景中工作:

lanscape version

我想我要花很长时间才能解释 :D

基本上,我创建了一个自定义的 UINavigationController,如上面的评论所述,将其称为 ActionBarNavigationController

在这个自定义 UINavigationController 中,我添加了一个自定义 UIView 来显示 ActionBar,右侧有下拉按钮。

下拉菜单是一个 UITableView,其中包含您选择的填充列表。

我在 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,它符合我在下面的类中创建的 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 自定义 View 的实例。它处理用户点击下拉按钮的交互。

#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,用于显示带有下拉按钮的操作栏。

#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

下拉单元格.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

1x 2x 3x

关于ios - 如何像Android一样在iOS中实现菜单,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29443154/

相关文章:

macos - xcode 像 php 或 perl 一样快速解析文本

ios - 每个屏幕上的 UINavigation 栏下方的 UIView

Xcode 6 Beta 2 - iOS 模拟器错误和元素重新排列

ios - PEM编码的椭圆曲线公钥转换iOS

css - 列表鼠标悬停不起作用

ios - 尝试将非 ARC 'CallHandler'(调用拦截器)转换为 ARK 遇到问题

android - 菜单项图标在 API 23 中重叠

CSS - 令人沮丧的菜单项 "selected_page"

ios - 使用 NavigationViewController 导航

ios - 多点连接 : Share Files to all peers simultaneously