如今的应用大多会采用抽屉效果来进行实现,下边附上一段简单的抽屉效果的实现代码,记录一下。当然要实现抽屉效果还可以有很多更简单的方式(比如使用第三方框架:MMDrawerController gitHub地址https://github.com/mutualmobile/MMDrawerController)。但了解一下底层代码的具体实现也是很有必要的。
1,首先定义一些可能会用到的宏
//抽屉顶部距离 底部一样
#define WNXScaleTopMargin 35
//app的高度
#define WNXAppWidth ([UIScreen mainScreen].bounds.size.width)
//app的宽度
#define WNXAppHeight ([UIScreen mainScreen].bounds.size.height)
//抽屉拉出来右边剩余比例
#define WNXZoomScaleRight 0.14
2,添加拖拽手势
//添加手势
UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(pan:)];
pan.delegate = self;
[self.view addGestureRecognizer:pan];
设置一个记录当前显示的控制器
//记录当前显示的控制器,用于添加手势拖拽
@property (nonatomic, weak) WNXViewController *showViewController;
3,实现拖拽手势。具体实现方式请看注释
#pragma mark - 手势
//拖拽Action
- (void)pan:(UIPanGestureRecognizer *)pan
{
CGFloat moveX = [pan translationInView:self.view].x;
//缩放的最终比例值
CGFloat zoomScale = (WNXAppHeight - WNXScaleTopMargin * 2) / WNXAppHeight;
//X最终偏移距离
CGFloat maxMoveX = WNXAppWidth - WNXAppWidth * WNXZoomScaleRight;
//没有缩放时,允许缩放
if (self.showViewController.isScale == NO) {
if (moveX <= maxMoveX + 5 && moveX >= 0) {
//获取X偏移XY缩放的比例
CGFloat scaleXY = 1 - moveX / maxMoveX * WNXZoomScaleRight;
CGAffineTransform transform = CGAffineTransformMakeScale(scaleXY, scaleXY);
self.showViewController.navigationController.view.transform = CGAffineTransformTranslate(transform, moveX / scaleXY, 0);
}
//当手势停止的时候,判断X轴的移动距离,停靠
if (pan.state == UIGestureRecognizerStateEnded) {
//计算剩余停靠时间
if (moveX >= maxMoveX / 2) {
CGFloat duration = 0.5 * (maxMoveX - moveX)/maxMoveX > 0 ? 0.5 * (maxMoveX - moveX)/maxMoveX : -(0.5 * (maxMoveX - moveX)/maxMoveX);
if (duration <= 0.1) duration = 0.1;
//直接停靠到停止的位置
[UIView animateWithDuration:duration delay:0 options:UIViewAnimationOptionCurveLinear animations:^{
CGAffineTransform tt = CGAffineTransformMakeScale(zoomScale, zoomScale);
self.showViewController.navigationController.view.transform = CGAffineTransformTranslate(tt, maxMoveX , 0);
} completion:^(BOOL finished) {
//将状态改为已经缩放
self.showViewController.isScale = YES;
//手动点击按钮添加遮盖
[self.showViewController rightClick];
}];
} else {//X轴移动不够一半 回到原位,不是缩放状态
[UIView animateWithDuration:0.2 animations:^{
self.showViewController.navigationController.view.transform = CGAffineTransformIdentity;
} completion:^(BOOL finished) {
self.showViewController.isScale = NO;
}];
}
}
}
else if (self.showViewController.isScale == YES) {
//已经缩放的情况下
//计算比例
CGFloat scaleXY = zoomScale - moveX / maxMoveX * WNXZoomScaleRight;
if (moveX <= 5) {
CGAffineTransform transform = CGAffineTransformMakeScale(scaleXY, scaleXY);
self.showViewController.navigationController.view.transform = CGAffineTransformTranslate(transform, (moveX + maxMoveX), 0);
}
//当手势停止的时候,判断X轴的移动距离,停靠
if (pan.state == UIGestureRecognizerStateEnded) {
//计算剩余停靠时间
if (-moveX >= maxMoveX / 2) {
CGFloat duration = 0.5 * (maxMoveX + moveX)/maxMoveX > 0 ? 0.5 * (maxMoveX + moveX)/maxMoveX : -(0.5 * (maxMoveX + moveX)/maxMoveX);
if (duration <= 0.1) duration = 0.1;
//直接停靠到停止的位置
[UIView animateWithDuration:duration delay:0 options:UIViewAnimationOptionCurveLinear animations:^{
self.showViewController.navigationController.view.transform = CGAffineTransformIdentity;
} completion:^(BOOL finished) {
//将状态改为已经缩放
self.showViewController.isScale = NO;
//手动点击按钮添加遮盖
[self.showViewController coverClick];
}];
} else {//X轴移动不够一半 回到原位,不是缩放状态
[UIView animateWithDuration:0.2 animations:^{
CGAffineTransform tt = CGAffineTransformMakeScale(zoomScale, zoomScale);
self.showViewController.navigationController.view.transform = CGAffineTransformTranslate(tt, maxMoveX, 0);
} completion:^(BOOL finished) {
self.showViewController.isScale = YES;
}];
}
}
}
}