在如今的App中很多应用都会有抽屉效果的身影,如比较热门的网易新闻和腾讯QQ。实际开发中实现抽屉效果主要是靠控制器之间的不断切换,来展示不同的View,已达到不同效果的展示。不过在本文中,主要是通过几个简单的UIView来模拟一下抽屉效果。下面就先上代码。
首先是创建3个不同的UIView:
// 创建三个view
// 蓝色
UIView *blueView = [[UIView alloc] initWithFrame:self.view.bounds];
blueView.backgroundColor = [UIColor blueColor];
[self.view addSubview:blueView];
self.blueView = blueView;
// 橙色
UIView *orangeView = [[UIView alloc] initWithFrame:self.view.bounds];
orangeView.backgroundColor = [UIColor orangeColor];
[self.view addSubview:orangeView];
self.orangeView = orangeView;
// 红色
UIView *redView = [[UIView alloc] initWithFrame:self.view.bounds];
redView.backgroundColor = [UIColor redColor];
[self.view addSubview:redView];
self.redView = redView;
同时把创建的3个UIView变成控制器的属性,方便之后改变其Frame.
使用KVO来监听redView的Frame属性的变化:
// 使用kvo监听红色view frame值的改变
[self.redView addObserver:self forKeyPath:@"frame" options:NSKeyValueObservingOptionNew context:nil];
第二步,实现触摸事件的相关方法
// 当手指在屏幕上移动的时候调用
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
self.draging = YES;
// 获得触摸对象
UITouch *touch = [touches anyObject];
// 获得上一个触摸点的位置
CGPoint previousPoint = [touch previousLocationInView:self.view];
// 获得当前触摸点的位置
CGPoint currentPoint = [touch locationInView:self.view];
// 计算x方向上的偏移量
CGFloat offsetX = currentPoint.x - previousPoint.x;
// 根据x方向的偏移量计算红色view的frame
self.redView.frame = [self rectWithOffsetX:offsetX];
}
// 当手指离开屏幕的时候调用
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
if (!self.draging && self.redView.frame.origin.x != 0) {
[UIView animateWithDuration:0.15 animations:^{
// 恢复到最初状态
self.redView.frame = self.view.bounds;
}];
return;
}
// 获得屏幕的宽度
CGFloat screenW = [UIScreen mainScreen].bounds.size.width;
// 获得红色view的x值
CGFloat redViewX = self.redView.frame.origin.x; // 250
if(redViewX > screenW * 0.5) {
// 如果大于屏幕的一半
redViewX = CZMaxX;
} else if(redViewX < -(screenW * 0.5)){ // -200 -300
// 如果红色view的x值小于屏幕宽度的一半
redViewX = CZMinX;
}
// 计算x方向的偏移量
CGFloat offsetX = redViewX - self.redView.frame.origin.x; // 0
[UIView animateWithDuration:0.15 animations:^{
self.redView.frame = (offsetX == 0)? self.view.bounds:[self rectWithOffsetX:offsetX];
}];
self.draging = NO;
}
/**
* 根据x方向的偏移量计算红色view的frame
*/
- (CGRect)rectWithOffsetX:(CGFloat)offsetX {
// 获得屏幕的宽度
CGFloat screenW = [UIScreen mainScreen].bounds.size.width;
CGFloat screenH = [UIScreen mainScreen].bounds.size.height;
// 计算y方向的偏移量
CGFloat offsetY = offsetX * CZMaxTopMargin / screenW;
if (self.redView.frame.origin.x < 0) {
offsetY *= -1;
}
// 获得当前红色view的frame
CGRect frame = self.redView.frame;
frame.origin.x += offsetX;
frame.origin.y += offsetY;
frame.size.height = screenH - 2 * frame.origin.y;
return frame;
}
使用到的宏定义:
/**
* 红色view最大的y值
*/
#define CZMaxTopMargin 100
/**
* 红色view最大的x值
*/
#define CZMaxX 250
/**
* 红色view最小的x值
*/
#define CZMinX -300
程序运行显示的UIView界面:
鼠标向右滑动的效果图:
鼠标向左滑动的效果图: