目前市场上很多APP都有抽屉效果的界面,界面大同小异,一下是我个人分析和实现的抽屉效果,我是以代码加注释的方式分析抽屉效果界面的搭建和效果的实现的.
实现效果图:
第一步:搭建界面
- (void)viewDidLoad {
[superviewDidLoad];
//搭建界面
[selfsetUpView];
}
- (void)setUpView{
//添加左边的View
UIView*leftV = [[UIViewalloc]initWithFrame:self.view.bounds];
//左边蓝色
leftV.backgroundColor= [UIColorblueColor];
[self.viewaddSubview:leftV];
添加右边的View
UIView*rightV = [[UIViewalloc]initWithFrame:self.view.bounds];
//右边縁色
rightV.backgroundColor= [UIColorgreenColor];
self.rightV= rightV;
[self.viewaddSubview:rightV];
//添加中间的View(中间一个最后添加,显示到最外面.)
UIView*mainV = [[UIViewalloc]initWithFrame:self.view.bounds];
//中间红色
mainV.backgroundColor= [UIColorredColor];
self.mainV= mainV;
[self.viewaddSubview:mainV];
}
//第二步.添加手势.能够让中间的红色View左右移动,要在控制器View加载完成时就要添加View
- (void)viewDidLoad {
[superviewDidLoad];
//搭建界面
[selfsetUpView];
//拖动手势
UIPanGestureRecognizer*pan = [[UIPanGestureRecognizeralloc]initWithTarget:selfaction:@selector(pan:)];
//添加手势
[self.mainVaddGestureRecognizer:pan];
}
//实现手势方法:
//当手指拖动时调用.
-(void)pan:(UIPanGestureRecognizer*)pan{
//获取手指在屏幕上面的偏移量
CGPointtransP = [pantranslationInView:self.mainV];
//在这里为什么不用Transform,是因为我们移动时,要改变的尺寸大小.用Transform只能改变它的位置.
self.mainV.transform = CGAffineTransformTranslate(self.mainV.transform, transP.x, 0);
//计算mainV的Frame
//单独抽出一个方法来计算mainV的frame.因为要计算它的Y值和高度.代码会很多.所以单独抽出一个方法
self.mainV.frame= [selfframeWithOffsetX:transP.x];
//每次移动时判断当前MainV的x值是大于0还是小于0.如果是大于0 ,显示左边,小于0显示右边
if(self.mainV.frame.origin.x>0) {
self.rightV.hidden=YES;
}elseif(self.mainV.frame.origin.x<0){
self.rightV.hidden=NO;
}
//注意要做复位
[pansetTranslation:CGPointZeroinView:self.mainV];
}
//最大Y值为100
#define maxY100
//根据偏移量计算mainV的frame.
- (CGRect)frameWithOffsetX:(CGFloat)offsetX{
//取出最原始的Frame
CGRectframe =self.mainV.frame;
frame.origin.x+= offsetX;
//获取屏幕的宽度
//(计算Y值如果下图:找最大值.当Main.x拖动最大的时候,Main.y值也最大.main.x最大为屏幕的宽度)
//设定一个最大Y值MaxY为100,正好.当max.x为屏幕的宽度时,最大Y等于100
//所以Y值等于 main.y = main.x * maxY / ScreenW;
100 = 375 * 100 / 375;)
//有可能frame.origin.x有可能是小于0,小于0的话,得出的Y值就会小于0,小于0就会出现,红色的View向上走.
//对结果取绝对值.
frame.origin.y=fabs(frame.origin.x*maxY/screenW);
//计算frame的高度
//(当前Main的高度等于屏幕的高度减去两倍的Y值.)
frame.size.height=screenH-2* frame.origin.y;
//返回计算好的frame.
returnframe;
}
//第三步:当手指松开时做到自动定位.
MainV定位到右侧的X值
#define targetR275
MainV定位到右侧的X值
#define targetL -275
//当手指拖动时调用.
-(void)pan:(UIPanGestureRecognizer*)pan{
//获取手指在屏幕上面的偏移量
CGPointtransP = [pantranslationInView:self.mainV];
//在这里为什么不用Transform,是因为我们移动时,要改变的尺寸大小.用Transform只能改变它的位置.
self.mainV.transform = CGAffineTransformTranslate(self.mainV.transform, transP.x, 0);
//计算mainV的Frame
//单独抽出一个方法来计算mainV的frame.因为要计算它的Y值和高度.代码会很多.所以单独抽出一个方法
self.mainV.frame= [selfframeWithOffsetX:transP.x];
//每次移动时判断当前MainV的x值是大于0还是小于0.如果是大于0 ,显示左边,小于0显示右边
if(self.mainV.frame.origin.x>0) {
self.rightV.hidden=YES;
}elseif(self.mainV.frame.origin.x<0){
self.rightV.hidden=NO;
}
//判断手指的状态
if(pan.state==UIGestureRecognizerStateEnded){
//当手指松开时进入执行
//记录最终判断结果后.定位的值.
CGFloattarget =0;
//当手指松开,要判断MainV的x值是否大于屏幕的一半.如果大于屏幕一半时,自动定位到右边一个位置.
if(self.mainV.frame.origin.x>screenW*0.5) {
target =targetR;
}elseif(CGRectGetMaxX(self.mainV.frame)
//当手指松开,要判断MainV的最大的X值是否小于屏幕的一半.如果小于屏幕的一半时,自动定位到左边的位置.
target =targetL;
}
最终定位的x值 - 当前的main.x的值. 求出便宜量.使其定位
CGFloatoffsetX = target -self.mainV.frame.origin.x;
//根据便宜量设置mainV的frame值
CGRectframe = [selfframeWithOffsetX:offsetX];
[UIViewanimateWithDuration:0.25animations:^{
//伴随动画设置frame
self.mainV.frame= frame;
}];
}
//注意要做复位
[pansetTranslation:CGPointZeroinView:self.mainV];
}