zoukankan      html  css  js  c++  java
  • 简单的抽屉效果

    简单的抽屉效果是由3 个View 组成,顶层默认显示的mainV,左边的leftV以及右边的rightV ,当mainV 监听到滑动时,计算滑动的偏移量,控制显示leftV或者rightV.

    废话不多说,上代码.

    一:所以,首先我们需要在头文件中定义三个View的属性,来给外界调用,实现设置对应的属性和效果:

    1 @property (nonatomic, weak, readonly) UIView *mainV;
    2 
    3 @property (nonatomic, weak, readonly) UIView *leftV;
    4 
    5 @property (nonatomic, weak, readonly) UIView *rightV;

    二:然后在实现文件中定义对应的宏,后面要用到:

    复制代码
     1 // @"frame"
     2 //自动提示宏 
     3 #define XMGkeyPath(objc, keyPath) @(((void)objc.keyPath, #keyPath))
     4 
     5 // 在宏里面如果在参数前添加了#,就会把参数变成C语言字符串
     6 
     7 // 获取屏幕的宽度
     8 #define screenW [UIScreen mainScreen].bounds.size.width
     9 
    10 // 获取屏幕的高度
    11 #define screenH [UIScreen mainScreen].bounds.size.height
    复制代码

    宏入门:宏定义的黑魔法 - 宏菜鸟起飞手册

    三:在ViewDidLoad中调用下面这个方法实现三个View的创建:

    复制代码
     1 // 添加所有的子控件
     2 - (void)setUpAllChildView
     3 {
     4     // left
     5     UIView *leftV = [[UIView alloc] initWithFrame:self.view.bounds];
     6     leftV.backgroundColor = [UIColor greenColor];
     7     [self.view addSubview:leftV];
     8     _leftV = leftV;
     9     
    10     // right
    11     UIView *rightV = [[UIView alloc] initWithFrame:self.view.bounds];
    12     rightV.backgroundColor = [UIColor blueColor];
    13     [self.view addSubview:rightV];
    14     _rightV = rightV;
    15     
    16     // main
    17     UIView *mainV = [[UIView alloc] initWithFrame:self.view.bounds];
    18     mainV.backgroundColor = [UIColor redColor];
    19     [self.view addSubview:mainV];
    20     _mainV = mainV;
    21 }
    复制代码

    四:在ViewDidLoad中为mainV界面添加滑动手势:

     1     // 添加拖拽手势
     2     UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(pan:)];
     3     
     4     [_mainV addGestureRecognizer:pan];
     5 

    使用KVO监听frame的变化:

    复制代码
    1     
    2     // KVO作用:时刻监听某个对象的某个属性的改变
    3     // _main frame属性的改变
    4     // Observer:观察者
    5     // KeyPath:监听的属性
    6     // NSKeyValueObservingOptionNew:表示监听新值的改变
    7     [_mainV addObserver:self forKeyPath:XMGkeyPath(_mainV, frame) options:NSKeyValueObservingOptionNew context:nil];
    8     
    复制代码

    五:实现滑动手势的方法,和监听属性变化的方法:

    复制代码
     1 #define targetR 300
     2 
     3 #define targetL -200
     4 
     5 - (void)pan:(UIPanGestureRecognizer *)pan
     6 {
     7     // 获取手势的偏移量
     8     CGPoint transP = [pan translationInView:_mainV];
     9     // 获取x轴的偏移量,相对于上一次
    10     CGFloat offsetX = transP.x;
    11     // 修改最新的main.frame,
    12     _mainV.frame = [self frameWithOffsetX:offsetX];
    13     // 复位
    14     [pan setTranslation:CGPointZero inView:_mainV];
    15     // 判断下当前手指有没有抬起,表示手势结束
    16     if (pan.state == UIGestureRecognizerStateEnded) { // 手指抬起,定位
    17         // x>屏幕的一半,定位到右边某个位置
    18         CGFloat target = 0;
    19         if (_mainV.frame.origin.x > screenW * 0.5) {
    20             target = targetR;
    21         }else if (CGRectGetMaxX(_mainV.frame) < screenW * 0.5){
    22             // 最大的x < 屏幕一半的时候,定义到左边某个位置
    23             target = targetL;
    24         }
    25         // 获取x轴的偏移量
    26         CGFloat offsetX = target - _mainV.frame.origin.x;
    27         [UIView animateWithDuration:0.25 animations:^{
    28             _mainV.frame = [self frameWithOffsetX:offsetX];
    29         }];
    30     }
    31 }
    32 
    33 #define XMGMaxY 100
    34 
    35 // 给定一个x轴的偏移量计算下最新main的frame
    36 - (CGRect)frameWithOffsetX:(CGFloat)offsetX
    37 {
    38     
    39     
    41     
    42     // 获取当前main的frame
    43     CGRect frame = _mainV.frame;
    44     
    45     // 计算当前的x,y,w,h
    46     // 获取最新的x
    47     CGFloat x = frame.origin.x + offsetX;
    48     
    49     // 获取最新的y
    50     CGFloat y = x / screenW * XMGMaxY;
    51     
    52     // 当用户往左边移动的时候,_main.x < 0,y需要增加,为正
    53     if (frame.origin.x < 0) {
    54         y = -y;
    55     }
    56     // 获取最新的h
    57     CGFloat h = screenH - 2 * y;
    58     // 获取缩放比例
    59     CGFloat scale = h / screenH;
    60     // 获取最新的w
    61     CGFloat w = screenW * scale;
    62     return CGRectMake(x, y, w, h);
    63 }
    复制代码

    监听属性的变化:

    复制代码
    1 // 只要监听的属性一改变,就会调用
    2 - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
    3 {
    4     if (_mainV.frame.origin.x > 0) { // 往右滑动,显示左边控件,隐藏右边控件
    5         _rightV.hidden = YES;
    6     }else if (_mainV.frame.origin.x < 0){ // 往左滑动,显示右边控件
    7         _rightV.hidden = NO;
    8     }
    9 }
    复制代码

    注意:KVO使用结束后一定要移除观察者

    1 // 注意:当对象被销毁的时候,一定要注意移除观察者
    2 - (void)dealloc
    3 {
    4     // 移除观察者
    5     [_mainV removeObserver:self forKeyPath:XMGkeyPath(_mainV, frame)];
    6 }

    六:为界面添加一个单击手势,实现单击屏幕还原

    1      // 给控制器的view添加一个点按
    2      
    3      UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tap)];
    4     
    5      [self.view addGestureRecognizer:tap];

    还原方法的实现:

    复制代码
     1 - (void)tap
     2 {
     3     if (_mainV.frame.origin.x != 0) {
     4         // 把_mainV还原最开始的位置
     5         
     6         [UIView animateWithDuration:0.25 animations:^{
     7             _mainV.frame = self.view.bounds;
     8             
     9         }];
    10         
    11     }
    12 }
    复制代码

    下面就是最终的效果: 

       

     

    本博文由博主根据资料或其他优秀博文整理而成,转载请注明出处,谢谢!
  • 相关阅读:
    数据库服务器计数器
    性能测试之操作系统计数器分析方法
    性能测试之Windows常见性能计数器
    企业级 SpringCloud 教程 (三) 服务消费者(Feign)
    企业级 SpringCloud 教程 (二) 服务消费者(rest+ribbon)
    企业级 SpringCloud 教程 (一) 服务的注册与发现(Eureka)
    Spring Cloud构建微服务架构:服务容错保护(Hystrix断路器)
    Spring Cloud构建微服务架构:服务容错保护(Hystrix服务降级)
    Spring Cloud构建微服务架构:服务容错保护(Hystrix依赖隔离)
    Spring Cloud构建微服务架构:分布式配置中心
  • 原文地址:https://www.cnblogs.com/Apolla/p/4733394.html
Copyright © 2011-2022 走看看