• 类似QQ侧滑菜单功能实现


    之前的那文章简单实现了菜单侧拉功能,但是做不到像QQ那样导航条和tabBar一起移动。。。之后在网上找资料,有了思路,就自个写了个demo试试水。


    先创建QHLMainController控制器,并把它设置成app的根控制器。


    在QHLMainController控制器中,懒加载添加一个tableView,并对tableView设置相对应的属性以及frame(frame的x设置为一个负值)!!添加一个tabBar控制器,并


    为tabBar控制器添加4个子控制器(分别为first,two,three,four)!!!并对tabBar控制器的view的frame 添加一个KVO监听,监听当tabBar控制器 的view的frame的改

    变,并执行相对应的代码。在tabBar控制器的第一个子控制器first控制器中,添加拖动手势,当拖动时候,根据拖动的偏移量来改变自身tabBar控制器的view的frame的


    值。当偏移量达到最大的时候  给view添加点击手势,当点击时候,使view的frame变回初始值!!当frame变回初值的时候,移除点击手势。

    在QHLMainController控制器中

     1 - (void)viewDidLoad {
     2     [super viewDidLoad];
     3     
     4     //添加懒加载的tableView
     5     [self.view addSubview:self.tableView];
     6     
     7     //设置主界面
     8     [self setUpMainUI];
     9 }
    10 
    11 /**
    12  *  设置主界面
    13  */
    14 
    15 - (void)setUpMainUI {
    16     //创建tabBar控制器并添加到根控制器中
    17     QHLTabBarController *tabVc = [[QHLTabBarController alloc] init];
    18     self.tabVc = tabVc;
    19     [self addChildViewController:tabVc];
    20     [self.view addSubview:tabVc.view];
    21     //对tabBar控制器view的frame属性添加一个监听
    22     [tabVc.view addObserver:self forKeyPath:@"frame" options:NSKeyValueObservingOptionNew context:nil];
    23     
    24 }
    25 /**
    26  *  tabBar控制器view的frame属性的监听事件
    27  */
    28 
    29 #define QHLViewControllerMaxOffsetX 250
    30 #define QHLLeftViewOriginX -50
    31 
    32 - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context {
    33     //计算偏移量
    34     CGFloat offsetX =QHLLeftViewOriginX - QHLLeftViewOriginX * (self.tabVc.view.frame.origin.x) / QHLViewControllerMaxOffsetX;
    35     //改变tableView的frame
    36     CGRect frame = self.tableView.frame;
    37     frame.origin.x = offsetX;
    38     self.tableView.frame = frame;
    39 }

    tableView的懒加载和dataSource方法就不放上来了。

     

     

    在tabBar控制器的子控制器first控制器中,先添加枚举型的结构体

    1 typedef NS_ENUM(NSInteger, QHLViewControllerState) {
    2     QHLViewControllerStateClosed = 0,
    3     QHLViewControllerStateOpening,
    4     QHLViewControllerStateOpened,
    5     QHLViewControllerStateClosing
    6 };

    首先在viewWillAppear:中添加拖动手势,并添加到当前view中,然后在viewWillDisappear:方法中把拖动手势移除掉。

    在viewDidLoad方法中:

    1.把自身的state状态设置成QHLViewControllerStateClosed

    2.添加navigationItem的leftBarButtonItem:封装一个UIButton,设置相关的属性设置、一个背景色以及添加一个点击方法

    点击方法如下:

     1 /**
     2  *  leftItem的点击事件
     3  */
     4 - (void)leftItemDidClick:(UIButton *)leftItem {
     5     if (self.state == QHLViewControllerStateClosed) {
     6         [self animatingOpen];
     7     } else {
     8         [self animatingClose];
     9     }
    10 }

    拖动手势事件方法实现:

     1 /**
     2  *  拖动手势的实现方法
     3  */
     4 - (void)panGestureRecognized:(UIPanGestureRecognizer *)panGestureRecognizer {
     5     CGPoint location = [panGestureRecognizer translationInView:self.view];  //位置
     6     CGRect frame = self.tabBarController.view.frame;
     7     //获取当前拖动手势的状态
     8     UIGestureRecognizerState state = panGestureRecognizer.state;
     9     
    10     switch (state) {
    11             //拖动手势开始时候
    12         case UIGestureRecognizerStateBegan:
    13             self.beginLocation = location; //开始位置
    14             if (self.state == QHLViewControllerStateClosed) {
    15 
    16                 [self willOpen];
    17             } else {
    18 
    19                 [self willClose];
    20             }
    21             break;
    22             //拖动手势进行中
    23         case UIGestureRecognizerStateChanged:
    24         {
    25             CGFloat offsetX = 0;   //偏移量X
    26             
    27             //根据自身的state来设置不同的offsetX
    28             if (self.state == QHLViewControllerStateOpening) {  //正在打开
    29                 offsetX = location.x - self.beginLocation.x;
    30             } else {   //正在关闭
    31                 offsetX = QHLViewControllerMaxOffsetX - (self.beginLocation.x - location.x);
    32             }
    33 
    34             if (offsetX >= QHLViewControllerMaxOffsetX) { //偏移量超过最大偏移值时
    35                 frame.origin.x = QHLViewControllerMaxOffsetX;
    36             } else if (offsetX <= 0) { //只有在关闭时候才会出现偏移量小于0的情况,而此种情况下,偏移量小于0,会使自身的x值小于0
    37                 frame.origin.x = 0;
    38             } else { //正在打开或者正在关闭
    39                 frame.origin.x = offsetX;
    40             }
    41             
    42             //计算透明度
    43             CGFloat alpha = 1 - offsetX / QHLViewControllerMaxOffsetX;
    44             self.leftItem.alpha = alpha; //设置导航条左侧item的透明度
    45             self.tabBarController.view.frame = frame;
    46             break;
    47         }
    48             //拖动手势结束时
    49         case UIGestureRecognizerStateEnded:
    50             if (self.state == QHLViewControllerStateOpening) { //正在打开
    51                 if (frame.origin.x >= QHLViewControllerMaxOffsetX / 2) { //判断此时的偏移量
    52                     [self animatingOpen];
    53                 } else {
    54                     [self animatingClose];
    55                 }
    56                 
    57             } else { //正在关闭
    58                 if (frame.origin.x >= QHLViewControllerMaxOffsetX / 2) { //判断此时的偏移量
    59                     [self animatingOpen];
    60                 } else {
    61                     [self animatingClose];
    62                 }
    63             }
    64             break;
    65             
    66         default:
    67             break;
    68     }
    69 }

    点击手势事件方法实现:

    1 - (void)tapGestureRecognized:(UITapGestureRecognizer *)tapGestureRecognizer {
    2     //点击事件  自动缩回侧拉界面
    3     [self animatingClose];
    4 }

    当tabBar控制器的view在偏移的时候,会调用下面的几个方法:

     1 /**
     2  * willOpen
     3  */
     4 - (void)willOpen {
     5     self.state = QHLViewControllerStateOpening;
     6 }
     7 
     8 /**
     9  * opened
    10  */
    11 - (void)opened {
    12     self.state = QHLViewControllerStateOpened;
    13     
    14     //设置点击手势
    15     self.tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapGestureRecognized:)];
    16     [self.view addGestureRecognizer:self.tapGestureRecognizer];
    17 }
    18 
    19 /**
    20  * willClose
    21  */
    22 - (void)willClose {
    23     self.state = QHLViewControllerStateClosing;
    24 }
    25 
    26 /**
    27  * closed
    28  */
    29 - (void)closed {
    30     self.state = QHLViewControllerStateClosed;
    31     [self.view removeGestureRecognizer:self.tapGestureRecognizer];
    32 }
    33 
    34 /**
    35  *  以动画形式打开
    36  */
    37 - (void)animatingOpen {
    38     [UIView animateWithDuration:0.5 delay:0 usingSpringWithDamping:1.0 initialSpringVelocity:0.7 options:UIViewAnimationOptionCurveLinear animations:^{
    39         self.tabBarController.view.frame = CGRectMake(QHLViewControllerMaxOffsetX, 0, self.view.frame.size.width, self.view.frame.size.height);
    40         
    41         self.leftItem.alpha = 0;
    42     } completion:^(BOOL finished) {
    43         [self opened];//改变自身的state状态以及移除点击手势
    44     }];
    45 }
    46 
    47 /**
    48  *  以动画形式关闭
    49  */
    50 - (void)animatingClose {
    51     [UIView animateWithDuration:0.5 delay:0 usingSpringWithDamping:1.0 initialSpringVelocity:0.7 options:UIViewAnimationOptionCurveLinear animations:^{
    52         self.tabBarController.view.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
    53         
    54         self.leftItem.alpha = 1;
    55     } completion:^(BOOL finished) {
    56         [self closed];  //改变自身的state状态以及添加点击手势
    57     }];
    58 }

    模拟器测试了下,基本实现了和QQ左上角的导航条item点击触发的相类似的功能~。~

    如果路过的大神有更好的实现方法求指导下!!!!

  • 相关阅读:
    【leetcode】下一个排列
    【leetcode】配对交换
    【leetcode】两个相同字符之间的最长子字符串
    052-126&127
    052-125
    052-124
    052-123
    052-122
    052-121
    052-120
  • 原文地址:https://www.cnblogs.com/qhlbk/p/5122947.html
Copyright © 2020-2023  润新知