文档章节

iOS开发之抽屉效果

shenhuniurou
 shenhuniurou
发布于 2016/04/03 00:29
字数 791
阅读 109
收藏 1

在显示在窗口的控制器上添加三个view(如果只需要往一边滑动就只加2个view)

先声明三个view

#import "ViewController.h"

@interface ViewController ()
@property(nonatomic, weak) UIView *mainV;
@property(nonatomic, weak) UIView *leftV;
@property(nonatomic, weak) UIView *rightV;
@end

添加view到控制器view上

#pragma mark - 添加子控件
- (void)setUpChildViews {
    
    UIView *leftV = [[UIView alloc]initWithFrame:self.view.bounds];
    
    leftV.backgroundColor = [UIColor orangeColor];
    
    [self.view addSubview:leftV];
    
    _leftV = leftV;
    
    UIView *rightV = [[UIView alloc]initWithFrame:self.view.bounds];
    
    rightV.backgroundColor = [UIColor groupTableViewBackgroundColor];
    
    [self.view addSubview:rightV];
    
    _rightV = rightV;
    
    UIView *mainV = [[UIView alloc]initWithFrame:self.view.bounds];
    
    mainV.backgroundColor = [UIColor yellowColor];
    
    [self.view addSubview:mainV];
    
    _mainV = mainV;
}

- (void)viewDidLoad {
    [super viewDidLoad];
    
    //添加子控件
    [self setUpChildViews];
    
    //添加Pan手势
    UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(pan:)];
    
    [self.view addGestureRecognizer:pan];
    
    //添加点按手势,在主视图上任意位置点击回到屏幕开始位置
    UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(tap)];
    
    [self.view addGestureRecognizer:tap];
    
}
#pragma mark - 手势识别方法
#define targetL -230
#define targetR 200
#define screenW [UIScreen mainScreen].bounds.size.width
- (void)pan:(UIPanGestureRecognizer *)pan {
    
    //获取手势移动的位置
    CGPoint tranP = [pan translationInView:self.view];
    
    //获取x的偏移量
    CGFloat offsetX = tranP.x;
    
    //修改mainV的frame
    _mainV.frame = [self frameWithOffsetX:offsetX];
    
    //判断mainV的x是否大于0
    [self observeValueForKeyPath:nil ofObject:nil change:nil context:nil];
    
    //复位
    [pan setTranslation:CGPointZero inView:self.view];
    
    //判断当手势结束的时候,定位
    if (pan.state == UIGestureRecognizerStateEnded) {
        
        CGFloat target = 0;
        
        if (_mainV.frame.origin.x > screenW * 0.5) {
            //定位到右边
            target = targetR;
        }else if(CGRectGetMaxX(_mainV.frame) < screenW * 0.5) {
            //定位到左边
            target = targetL;
        }
        
        //获取X轴需要移动的偏移量
        CGFloat offsetX = target - _mainV.frame.origin.x;
        
        [UIView animateWithDuration:0.25 animations:^{
            
            _mainV.frame = target == 0 ? self.view.bounds : [self frameWithOffsetX:offsetX];

        }];
        
    }
    
}
- (void)tap {
    
    [UIView animateWithDuration:0.25 animations:^{
        _mainV.frame = self.view.bounds;
    }];
    
}
#define kMaxY 80
#pragma mark - 根据offsetX计算mainV的frame
- (CGRect)frameWithOffsetX:(CGFloat)offsetX {
    
    //获取上一次的frame
    CGRect frame = _mainV.frame;
    
    //获取屏幕的高度
    CGFloat screenH = [UIScreen mainScreen].bounds.size.height;
    
    //获取屏幕的宽度
    //CGFloat screenW = [UIScreen mainScreen].bounds.size.width;
    
    //X轴平移一点对应Y轴需要平移的距离
    CGFloat offsetY = offsetX * kMaxY / screenW;
    
    //获取上一次的高度
    CGFloat preH = frame.size.height;
    
    //获取上一次的宽度
    CGFloat preW = frame.size.width;
    
    //获取当前高度
    CGFloat curH = preH - 2 * offsetY;
    //如果是向左滑动
    if(frame.origin.x < 0) {
        curH = preH + 2 * offsetY;
    }
    
    //获取尺寸的缩放比例
    CGFloat scale = curH / preH;
    
    //获取当前宽度
    CGFloat curW = preW * scale;
    
    //获取当前x
    frame.origin.x += offsetX;
    
    //获取当前y
    CGFloat y = (screenH - curH) / 2;
    frame.origin.y = y;
    
    frame.size.width = curW;
    frame.size.height = curH;
    
    return frame;
    
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context {
    
    if(_mainV.frame.origin.x > 0) {//往右边滑动
        _rightV.hidden = YES;
    }else if(_mainV.frame.origin.x < 0) {//往左边滑动
        _rightV.hidden = NO;
    }
    
}


如果想要在mainV主视图中显示tableView,就新创建一个TableViewController,在这里面显示tableView的数据,

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {

    return 30;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    
    
    static NSString *ID = @"cell";
    
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
    
    if(cell == nil) {
        cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ID];
    }
    
    cell.textLabel.text = [NSString stringWithFormat:@"第%ld行", indexPath.row];
    
    return cell;
}


再创建一个在storyboard中显示的控制器XXMainViewController,继承自实现了抽屉效果的ViewController,并且在storyboard中将class改为这个控制的类名,还要将显示tableView的控制成为他的子控制器

- (void)viewDidLoad {
    [super viewDidLoad];
    
    XXViewController *vc = [[XXViewController alloc]init];
    vc.view.frame = self.view.bounds;
    
    //让vc成为主视图控制器的子控制器
    [self addChildViewController:vc];
    
    //主视图展示tableView
    [self.mainV addSubview:vc.view];
    
}


为了在XXMainViewController中只能访问mainV而不能修改他的值,所以将子控件的view暴露在ViewController.h中,并添加read-only

#import <UIKit/UIKit.h>

@interface ViewController : UIViewController
@property(nonatomic, weak, readonly) UIView *mainV;
@property(nonatomic, weak, readonly) UIView *leftV;
@property(nonatomic, weak, readonly) UIView *rightV;
@end

运行效果图:


© 著作权归作者所有

共有 人打赏支持
shenhuniurou
粉丝 20
博文 78
码字总数 63826
作品 0
广州
Android工程师
私信 提问
使用 React Native 一年后的感受

当我在面试Discord的时候,技术主管Stanislav跟我说: React Native代表着未来。等它一发布,我们就会用它从零构建iOS应用。 作为一名原生iOS开发者,基于先前使用PhoneGap的经验,我非常怀疑...

oschina
2016/06/22
66.1K
31
传 Android N 或取消沿用多年的应用抽屉

据科技网站PhoneArena报道,今天的一条消息显示,下一代Android系统(传说中的Android N)将取消沿用多年的应用抽屉设计,这一新系统将于今年年末面世。可靠消息称,在最新的预览版安卓7.0中...

oschina
2016/02/22
4.5K
14
GitHub 上排名前 100 的 Objective-C 项目简介

主要对当前 GitHub 排名前 100 的项目做一个简单的简介, 方便初学者快速了解到当前 Objective-C 在 GitHub 的情况. 若有任何疑问可通过微博@李锦发联系我 项目名称 项目信息 1. AFNetworkin...

oschina
2015/04/11
33.2K
28
iOS涂色涂鸦效果、Swift仿喜马拉雅FM、抽屉转场动画、拖拽头像、标签选择器等源码

iOS精选源码 LeeTagView 标签选择控件(http://www.code4app.com/thread-31033-1-1.html) 为您的用户显示界面添加美观的加载视图(http://www.code4app.com/thread-31038-1-1.html) Swift4: 可......

sunnyaigd
2018/09/19
0
0
iOS高仿QQ录音、智能语音诗歌、高仿微信图片浏览源码

iOS精选源码 好看实用的日期时间选择器--CCTimePicker 高仿QQ录音功能 QQ侧滑抽屉效果 MMActionSheet介绍(自定义的类似于微信的UIActionSheet弹出框组件) 智能语音查询诗歌 仿课程表表格效果...

sunnyaigd
2017/10/25
0
0

没有更多内容

加载失败,请刷新页面

加载更多

linux 扩展lv

相关概念 逻辑卷可以实现硬盘空间的动态划分和管理。 1】 物理卷 LV 处于最低层,可以是物理硬盘上的分区,也可以是整个物理硬盘 2】 卷组 VG 卷组建立在物理卷之上,一个卷组至少要包括一个...

hnairdb
23分钟前
1
0
如何快速定位Ruby函数源码

如何快速定位Ruby函数源码 1、gem gem which sidekiq 2、bundle bundle show redis 3、CTags Sublime extend ActiveSupport::Concernrescue_fromcurrent_company.cc_ad_tasks.creat......

mingle
24分钟前
1
0
基于 DataLakeAnalytics 的数据湖实践

随着软硬件各方面条件的成熟,数据湖(Data Lake)已经越来越受到各大企业的青睐, 与传统的数仓实践不一样的是,数据湖不需要专门的“入仓”的过程,数据在哪里,我们就从哪里读取数据进行分析...

阿里云云栖社区
26分钟前
1
0
word文档处理成富文本生成sql语句导入mysql

问题:需要将大量的已存在的word文档导入到web项目里在网站展示,不可能通过编辑录入的方式处理,通过程序实现。 解决思路:通过读取word文档处理成html,再获取html富文本内容,拼接成sql,...

S三少S
32分钟前
42
0
WAF开放规则定义权:专家策略+用户自定义策略=Web安全

在第一期“漫说安全”栏目中,我们用四格漫画的形式介绍了基于深度学习的阿里云WAF到底智能在哪里,能帮客户解决什么问题。 在今天的这期栏目里,我们依然通过漫画这种通俗易懂的方式,与大家...

迷你芊宝宝
36分钟前
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部