How to implement menu in iOS like Android

2019-03-31 10:10发布

I need to implement menu for iOS like android.menu means button on navigation bar(right side).

If I click that menu will display.

I am using a storyboard.

2条回答
迷人小祖宗
2楼-- · 2019-03-31 10:39

I would use a Popover rather than a complete custom menu. On iPhones it is suggested to use a full screen modal presentation rather than a popover menu, but it is still possible.

This image is from the Popover documentation.

enter image description here

For more details on how to do it, see this answer.

查看更多
ら.Afraid
3楼-- · 2019-03-31 10:40

So you want something like this:

app demo screenshots

Even works in landscape:

lanscape version

I think it's going to take forever for me to explain :D

Basically I created a custom UINavigationController as mentioned in the comments above, called it ActionBarNavigationController

From this custom UINavigationController, I added a custom UIView to display the ActionBar with the drop down button on the right.

The drop down menu is a UITableView with a populated list of your choice.

I used protocol in iOS to handle the tap even on each row of the drop down menu.

Everything was done purely in code. You can add these files to your project if you like, I've provided the code in full below where necessary.

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 is just your ordinary UIViewController that conforms to the ActionBarNavControllerDelegate that I created in the class below. Make sure you include it.

#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

This ActionBarNavController contains an instance of the ActionBar custom view. It handles the interactions of the user tapping on the drop down 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

This ActionBar class is the custom UIView to show the action bar with drop down 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

This custom UITableViewCell class controls the look and feel of the drop down menu cells.

#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

Drop Down Icon

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

1x2x3x

查看更多
登录 后发表回答