iOS开发-18.两种方法实现抽屉效果

1.抽屉效果实现方法1:利用触摸方法touches实现

配图

// 触摸事件实现
#import "ZJDrawerTouchViewController.h"
#define SCREEN [UIScreen mainScreen].bounds
#define kScreenW [UIScreen mainScreen].bounds.size.width
#define kScreenH [UIScreen mainScreen].bounds.size.height
@interface ZJDrawerTouchViewController ()
/**
 * 左部视图
 */
@property (nonatomic, weak) UIView *leftView;
/**
 * 主视图
 */
@property (nonatomic, weak) UIView *mainView;
/**
 * 右边视图
 */
@property (nonatomic, weak) UIView *rightView;

@end

@implementation ZJDrawerTouchViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // 添加子视图
    [self setUpAllSubViews];
}

// 重写touches:move:方法,实现简单抽屉效果
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
    // 获取当前和前一次触摸点的位置
    UITouch *touch = [touches anyObject];
    CGPoint preP = [touch previousLocationInView:self.mainView];
    CGPoint curP = [touch locationInView:self.mainView];
    // 计算X方向偏移位置
    CGFloat offsetX = curP.x - preP.x;
    // 根据当前偏移值计算最新的frame
    _mainView.frame = [self rectWithOffsetX:offsetX];
    // 判断是否需要隐藏视图
    [self shouldHideRightView];
}

#define targetMax 300
#define targetMin -200
// 重写touches:end:方法,判断结束触摸点时的位置调整frame
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
    // 判断结束触摸时,mainView的位置
    // 纪录目标当前x值
    CGFloat target = 0;
    if (_mainView.frame.origin.x > kScreenW * 0.5) { // 向右移动到超过一半的屏幕
        target = targetMax;
    }else if (CGRectGetMaxX(_mainView.frame) < kScreenW * 0.5){ // 向左移动超过屏幕的一半
        target = targetMin;
    }
    // 根据目标位置的值计算当前偏移位置
    CGFloat offsetX = target - _mainView.frame.origin.x;
    // 根据当前偏移位置计算最新的位置
    [UIView animateWithDuration:0.25 animations:^{
        _mainView.frame = [self rectWithOffsetX:offsetX];
    }];
}

// 重写touches:begin:方法
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
    // 判断当前主视图的x值
    if (_mainView.frame.origin.x != 0) { // 若是不为0,则点击控制器任何位置,主视图会回复到初始位置(即和控制器View的frame相同)
        [UIView animateWithDuration:0.25 animations:^{
            _mainView.frame = SCREEN;
        }];
    }
}

// 判断右边视图是否隐藏
-(void)shouldHideRightView{
    if (_mainView.frame.origin.x > 0) { // 向右移动
        // 隐藏右边的视图
        self.rightView.hidden = YES;
    }else if (_mainView.frame.origin.x < 0){ // 向左移动
        // 显示右边的视图
        self.rightView.hidden = NO;
    }
}

// 根据当前的x偏移量,计算mainView的frame
// Y值最大为100
#define kMaxY 100
-(CGRect)rectWithOffsetX:(CGFloat)offsetX{
    CGFloat curX = _mainView.frame.origin.x + offsetX;
    CGFloat curY = curX/kScreenW * kMaxY;
    if (curX < 0) { // 若是左移
        curY = -curY;
    }
    // 高度值为屏幕高度减去当前y值的2倍,即离屏幕上下的距离都是y
    CGFloat curH = kScreenH - 2 * curY;
    // 根据高度比计算当前宽度
    CGFloat curW = curH/kScreenH * kScreenW;

    // 返回计算的frame值
    return  CGRectMake(curX, curY, curW, curH);

}
// 添加抽屉视图
-(void)setUpAllSubViews{
    // 左边视图
    UIView *leftView = [[UIView alloc] initWithFrame:SCREEN];
    leftView.backgroundColor = [UIColor greenColor];
    [self.view addSubview:leftView];
    _leftView = leftView;
    // 右边视图
    UIView *rightView = [[UIView alloc] initWithFrame:SCREEN];
    rightView.backgroundColor = [UIColor blueColor];
    [self.view addSubview:rightView];
    _rightView = rightView;
    // 主视图
    UIView *mainView = [[UIView alloc] initWithFrame:SCREEN];
    mainView.backgroundColor = [UIColor purpleColor];
    [self.view addSubview:mainView];
    _mainView = mainView;
}
@end

2.抽屉效果实现方法二:手势事件实现

// 手势实现
#import "ZJDrawerViewController.h"
#define SCREEN [UIScreen mainScreen].bounds
#define kScreenW [UIScreen mainScreen].bounds.size.width
#define kScreenH [UIScreen mainScreen].bounds.size.height
#define kMaxY 100
@interface ZJDrawerViewController ()
/**
 * 左部视图
 */
@property (nonatomic, weak) UIView *leftView;
/**
 * 主视图
 */
@property (nonatomic, weak) UIView *mainView;
/**
 * 右边视图
 */
@property (nonatomic, weak) UIView *rightView;

@end

@implementation ZJDrawerViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    // 添加子视图
    [self setUpAllSubViews];
    // 添加手势
    UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(pan:)];

    // 添加拖拽手势
    [_mainView addGestureRecognizer:pan];

    // 给控制器添加点按手势
    UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tap)];
    [self.view addGestureRecognizer:tap];
}

// 控制器的View点按手势执行方法
-(void)tap{
    // 判断当前主视图的x值是否为0,若为0,则回复到初始位置
    if (_mainView.frame.origin.x != 0) {
        [UIView animateWithDuration:0.25 animations:^{
            _mainView.frame = SCREEN;
        }];
    }
}

#define targetMaxX 300 // 向右自动跳转最大x值
#define targetMinX -200 // 向左跳转最小x值

//  实现手势方法
-(void)pan:(UIPanGestureRecognizer *)pan{
    // 获取当前手势偏移量
    CGPoint curP = [pan translationInView:_mainView];

    // 视图X方向偏移
    //    _mainView.transform = CGAffineTransformTranslate(_mainView.transform, curP.x, 0);
    _mainView.frame = [self rectWithOffsetX:curP.x];

    // 复位
    [pan setTranslation:CGPointZero inView:_mainView];

    // 根据偏移方向显示后面的视图
    [self shouldHideRightView];

    // 判断手指是否抬起
    if (pan.state == UIGestureRecognizerStateEnded) { // 手指抬起
        CGFloat target = 0;
        if (_mainView.frame.origin.x > kScreenW * 0.5) { // 当前x值超过屏幕宽度一半
            target = targetMaxX;
        }else if(CGRectGetMaxX(_mainView.frame) < kScreenW * 0.5){ // 当前x小于屏幕宽度的一半
            target = targetMinX;
        }
        // 计算当前偏移值
        CGFloat offsetX = target - _mainView.frame.origin.x;

        // 根据当前偏移量计算最新的frame值
        [UIView animateWithDuration:0.25 animations:^{
            _mainView.frame = [self rectWithOffsetX:offsetX];
        }];
    }

}

// 判断当前偏移方向
-(void)shouldHideRightView{

    if (_mainView.frame.origin.x > 0) { // 往右滑动,显示左边控件,隐藏右边控件
        _rightView.hidden = YES;
    }else if (_mainView.frame.origin.x < 0){ // 往左滑动,显示右边控件
        _rightView.hidden = NO;
    }

}


// 根据当前的x偏移量,计算mainView的frame
-(CGRect)rectWithOffsetX:(CGFloat)offsetX{
    CGFloat curX = _mainView.frame.origin.x + offsetX;
    CGFloat curY = curX/kScreenW * kMaxY;
    if (curX < 0) { // 若是左移
        curY = -curY;
    }
    // 高度值为屏幕高度减去当前y值的2倍,即离屏幕上下的距离都是y
    CGFloat curH = kScreenH - 2 * curY;
    // 根据高度比计算当前宽度
    CGFloat curW = curH/kScreenH * kScreenW;

    // 返回计算的frame值
    return  CGRectMake(curX, curY, curW, curH);

}


// 添加子视图
-(void)setUpAllSubViews{
    // 左边视图
    UIView *leftView = [[UIView alloc] initWithFrame:SCREEN];
    leftView.backgroundColor = [UIColor greenColor];
    [self.view addSubview:leftView];
    _leftView = leftView;
    // 右边视图
    UIView *rightView = [[UIView alloc] initWithFrame:SCREEN];
    rightView.backgroundColor = [UIColor blueColor];
    [self.view addSubview:rightView];
    _rightView = rightView;
    // 主视图
    UIView *mainView = [[UIView alloc] initWithFrame:SCREEN];
    mainView.backgroundColor = [UIColor purpleColor];
    [self.view addSubview:mainView];
    _mainView = mainView;
}

@end
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值