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