下拉菜单的简单实现原理

效果

下拉菜单的简单实现原理_第1张图片
Simulator Screen Shot Dec 1, 2015, 22.54.17.png

需要实现两个功能:

1、点击Expand展开菜单。
2、点击Eapend或透明处收起菜单

主要分两个步骤

1、将菜单添加到View上
2、菜单切入View动画
具体如下图:

下拉菜单的简单实现原理_第2张图片
Untitled.001.jpeg
首先将初始化ViewController
ViewController.m
- (void)viewDidLoad {
  [super viewDidLoad];

  self.title = @"Nav";
  self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"Menu" style:UIBarButtonItemStylePlain target:self action:@selector(expandAction:)];
}

-(void)expandAction:(id)sender {
}
接下来定义菜单视图
ExpendManu.h
#import 

@interface ExpandMenu : UIView
- (void)showExpendMenu;
- (void)dismissExpandMenu;
@end
ExpandMenu.m
#import "ExpandMenu.h"

@interface ExpandMenu() 
@property (nonatomic, strong) UITableView *tableView;
@end

@implementation ExpandMenu
static CGFloat kTableViewHeight = 300.0;

- (instancetype)initWithFrame:(CGRect)frame {
  self = [super initWithFrame:frame];
  if (self) {
    [self addSubview:self.tableView];
  }
   return self;
}

- (UITableView *)tableView{
  if (!_tableView) {
      _tableView = ({
          //注意tableView的初始位置
          UITableView *tempTableView = [[UITableView alloc] initWithFrame:CGRectMake(0, -kTableViewHeight, self.frame.size.width, kTableViewHeight)];
          tempTableView.backgroundColor = [UIColor whiteColor];
          tempTableView;
    });
  }
  return _tableView;
}

- (void)showExpandMenu
{//设置frame将tableView从屏幕外移入屏幕内
    [UIView animateWithDuration:0.2 animations:^{
        self.tableView.frame = CGRectMake(0, 0, self.frame.size.width, kTableViewHeight);
        self.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.4];
    }];
}

- (void)dismissExpandMenu
{
    [UIView animateWithDuration:0.2 animations:^{
        self.tableView.frame = CGRectMake(0, -kTableViewHeight, self.frame.size.width, kTableViewHeight);
        self.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0];
    } completion:^(BOOL finished) {
        [self removeFromSuperview];
    }];
}

定义好ExpandMenu后,再来实现ViewController中的expandAction,点击Menu具有两个功能:展开菜单和收起菜单,因此,最好将ExpandMenu作为ViewController的属性。

ViewController.m
@property (nonatomic, strong) ExpandMenu *expandMenu;

- (void)expandAction:(id)sender
{
    self.expandMenu = [[ExpandMenu alloc] initWithFrame:CGRectMake(0, 64, CGRectGetWidth(self.view.frame), CGRectGetHeight(self.view.frame))];
    [self.view addSubview:self.expandMenu];
    [self.expandMenu showExpandMenu];
}

现在还需要实现点击Menu移除ExpandMenu,这时可用在ExpandMenu中设个变量,用来保存Menu是否展开的状态,然后ViewController根据该值判断是否展开。
在ExpandMenu.h中添加

@property (nonatomic, assign, readonly) BOOL isExpand;

在 ExpandMenu.m 中添加

  @property (nonatomic, assign, readwrite) BOOL isExpand;

更新showExpandMenu方法

 - (void)showExpandMenu
{//设置frame将tableView从屏幕外移入屏幕内
    [UIView animateWithDuration:0.2 animations:^{
        self.tableView.frame = CGRectMake(0, 0, self.frame.size.width, kTableViewHeight);
        self.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.4];
    }];
    self.isExpand = YES;
}

- (void)dismissExpandMenu
{
    [UIView animateWithDuration:0.2 animations:^{
        self.tableView.frame = CGRectMake(0, -kTableViewHeight, self.frame.size.width, kTableViewHeight);
        self.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0];
    } completion:^(BOOL finished) {
        [self removeFromSuperview];
    }];
    self.isExpand = NO;
}

现在可以根据isExpand判断展开情况了:
ViewController.m
- (void)expendAction:(id)sender
{
if (self.expandMenu.isExpand) {
[self.expandMenu dismissExpandMenu];
return;
}
self.expandMenu = [[ExpandMenu alloc] initWithFrame:CGRectMake(0, 64, CGRectGetWidth(self.view.frame), CGRectGetHeight(self.view.frame))];
[self.view addSubview:self.expandMenu];
[self.expandMenu showExpandMenu];
}
到这里还差点击背景收起Menu了,只要给View添加个手势就好了:
ExpandMenu.m
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self addSubview:self.tableView];

        UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(backgroundViewTapped:)];
        tapGesture.delegate = self;
        [self addGestureRecognizer:tapGesture];
    }
    return self;
}

- (void)backgroundViewTapped:(id)sender
{
    [self dismissExpandMenu];
}

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
    if ([touch.view isDescendantOfView:self.tableView]) {
        return NO;
    }
    return YES;
}

这里需要实现UIGestureRecognizerDelegate,目的是为了防止点击tableView也会收起ExpandMenu。
到这里基本就完成了。
附上代码:
链接: http://pan.baidu.com/s/1gdyNE6n 密码: u6xy

你可能感兴趣的:(下拉菜单的简单实现原理)