【问题标题】:How to implement menu in iOS like Android如何在 iOS 等 Android 中实现菜单
【发布时间】:2015-06-09 04:34:53
【问题描述】:

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

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

我正在使用故事板。

【问题讨论】:

  • 你想要滑出菜单吗?
  • 我认为滑出式菜单会在侧视图中显示,但在我的要求中,我需要在同一个控制器中显示菜单(菜单按钮存在的地方)。
  • 也许使用 ContainerView 并且您控制了它如何显示屏幕,fe。按下按钮并查看出现的屏幕,
  • 您可以在代码中将子视图添加到导航控制器的视图属性中。我认为这可能是添加您的“子视图”菜单的地方。

标签: ios menu xcode6 uinavigationbar


【解决方案1】:

所以你想要这样的东西:

甚至可以在风景中工作:

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

基本上,我创建了一个自定义 UINavigationController,如上面 cmets 中所述,将其命名为 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 自定义视图的实例。它处理用户点击下拉按钮的交互。

#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

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

【讨论】:

    【解决方案2】:

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

    此图片来自Popover documentation

    有关如何操作的更多详细信息,请参阅this answer

    【讨论】:

      猜你喜欢
      • 2017-07-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-30
      • 1970-01-01
      • 1970-01-01
      • 2018-10-24
      相关资源
      最近更新 更多