抽屉效果功能实现

一、.h文件

@interfaceHMDrawViewController :UIViewController

@property(nonatomic,weak,readonly)UIView*mainView;
@property(nonatomic,weak,readonly)UIView*leftView;
@property(nonatomic,weak,readonly)UIView*rightView;

@end


二、.m文件

@interfaceHMDrawViewController()


@property(nonatomic,assign)BOOLisDraging;
@end

@implementationHMDrawViewController


- (void)viewDidLoad
{
// UIViewController
[superviewDidLoad];
// Do any additional setup after loading the view.

// 1.添加子控件
[selfaddChildView];
#warning第三步观察_mainView的frame改变
// 2.监听
/**
*给_mainView添加一个观察者
*
* KeyPath:监听frame这个属性
*
* options:监听新值的改变
*/
[_mainViewaddObserver:selfforKeyPath:@"frame"options:NSKeyValueObservingOptionNewcontext:nil];

}

//当_mainView的frame属性改变的时候就会调用
- (void)observeValueForKeyPath:(NSString*)keyPath ofObject:(id)object change:(NSDictionary*)change context:(void*)context
{
NSLog(@"%@",NSStringFromCGRect(_mainView.frame));

if(_mainView.frame.origin.x<0) {//往左移动
//显示右边
_rightView.hidden=NO;
//隐藏左边
_leftView.hidden=YES;
}elseif(_mainView.frame.origin.x>0){//往右移动
//显示左边
_rightView.hidden=YES;
//隐藏右边
_leftView.hidden=NO;

}
}

#warning第一步
- (void)addChildView
{
// left
UIView*leftView = [[UIViewalloc]initWithFrame:self.view.bounds];
leftView.backgroundColor= [UIColorgreenColor];
[self.viewaddSubview:leftView];
_leftView= leftView;

// right
UIView*rightView = [[UIViewalloc]initWithFrame:self.view.bounds];
rightView.backgroundColor= [UIColorblueColor];
[self.viewaddSubview:rightView];
_rightView= rightView;

// mainView
UIView*mainView = [[UIViewalloc]initWithFrame:self.view.bounds];
mainView.backgroundColor= [UIColorredColor];
[self.viewaddSubview:mainView];
_mainView= mainView;
}

#warning第二步
- (void)touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event
{
//获取UITouch对象
UITouch*touch = [touchesanyObject];

//获取当前点
CGPointcurrentPoint = [touchlocationInView:self.view];

//获取上一个点
CGPointprePoint = [touchpreviousLocationInView:self.view];

// x轴偏移量:当手指移动一点的时候,x偏移多少
CGFloatoffsetX = currentPoint.x- prePoint.x;

//设置当前主视图的frame
_mainView.frame= [selfgetCurrentFrameWithOffsetX:offsetX];


_isDraging=YES;
}
#warning第四步
#define HMMaxY60
//当手指偏移一点,根据X轴的偏移量算出当前主视图的frame
- (CGRect)getCurrentFrameWithOffsetX:(CGFloat)offsetX
{
CGFloatscreenW = [UIScreenmainScreen].bounds.size.width;
CGFloatscreenH = [UIScreenmainScreen].bounds.size.height;

//获取y轴偏移量,手指每移动一点,y轴偏移多少
CGFloatoffsetY = offsetX *HMMaxY/ screenW;

CGFloatscale = (screenH -2* offsetY) / screenH;

if(_mainView.frame.origin.x<0) {//往左边滑动
scale = (screenH +2* offsetY) / screenH;
}

//获取之前的frame
CGRectframe =_mainView.frame;
frame.origin.x+= offsetX;
frame.size.height= frame.size.height*scale;
frame.size.width= frame.size.width*scale;
frame.origin.y= (screenH - frame.size.height) *0.5;

returnframe;
}

注意:

抽屉效果的固定的高度是写死的,可以定义一个宏,方便后期的维护。
算法:

offsetY =offsetX*60/320
scale = currentH / screenH
currentH = screenH –2* offsetY

x = frame. origin.x + offsetX
h = frame.size.height * scale
w = frame.size.weight * scale
y =( screenH – h ) *0.5


#define HMRTarget250
#define HMLTarget -220
/*
_mainView.frame.origin.x > screenW * 0.5定位到右边
CGRectGetMaxX(_mainView.frame) < screenW * 0.5定位到左边-220

*/
//定位
- (void)touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event
{
//复位
if(_isDraging==NO&&_mainView.frame.origin.x!=0) {
[UIViewanimateWithDuration:0.25animations:^{

_mainView.frame=self.view.bounds;
}];
}
CGFloatscreenW = [UIScreenmainScreen].bounds.size.width;
CGFloattarget =0;
if(_mainView.frame.origin.x> screenW *0.5) {//定位到右边
target =HMRTarget;
}elseif(CGRectGetMaxX(_mainView.frame) < screenW *0.5) {//定位到左边
target =HMLTarget;
}
[UIViewanimateWithDuration:0.25animations:^{

if(target) {//在需要定位左边或者右边

//获取x轴偏移量
CGFloatoffsetX = target -_mainView.frame.origin.x;

//设置当前主视图的frame
_mainView.frame= [selfgetCurrentFrameWithOffsetX:offsetX];

}else{//还原
_mainView.frame=self.view.bounds;
}
}];
_isDraging=NO;
}


注意:

复位的时候,需要定义一个成员变量记录。
@end


注意:

知识点1:KVO观察者模式,给_mainView添加一个观察者,KeyPath:监听frame这个属性,options:监听新值的改变,当frame属性的值发生改变的时候就会调用下面这个方法。

- (void)observeValueForKeyPath:(NSString*)keyPath ofObject:(id)object change:(NSDictionary*)change context:(void*)context;

知识点2:抽屉效果的算法。


萌萌的IT人