冲动
最近接手的一个老项目有个侧滑菜单的需求,这个老项目的侧滑菜单用了网络上的一个第三方库,但是这个库竟然没有处理好导航条的显示,以至于项目中很多需要导航条展示信息的视图都通过添加subView的方式模仿了导航条。这简直是暴殄天物啊,放着真正的导航栏那强大的作用不用,浪费了多少时间和精力啊,都是青春啊,开发的前路上早已挖了无数的坑等着身心疲惫的我们往里跳啊。对此深恶痛绝的我,早就下了不杀此贼誓不罢休的决心。好吧,最近看三国看的有点多了。
暗渡陈仓
本人的手机QQ侧滑菜单
实在忍不了,换了小图了
哎,炫酷没法比啊。
iOS5之后每个UIViewController都可以轻松当一个容器了,可以同时管理许多其他的UIViewController了。
addChildViewController:
willMoveToParentViewController:
didMoveToParentViewController:
现在的话我有两个子视图控制器了,把他们的view分别放在了我自定义的menuViewContainer和contentViewContainer这两个View里。OK,基础已打好。
理所应当,我在contentViewCcontainer上添加一个滑动手势,滑动时移动视图的位置就行了。那怎么确定手指在滑动时相应的视图应该滑动到哪呢?滑动到哪里结束呢?怎么确定同时改缩放到什么程度呢?
这些问题我本来想一一说讲一遍,发现自己太啰嗦,又不知道该怎么讲,所以还是直接上代码吧。
- (void)panGestureRecognizer:(UIScreenEdgePanGestureRecognizer *)recognizer{
CGPoint point = [recognizer translationInView:self.view];
if(recognizer.state == UIGestureRecognizerStateBegan) {
[self updateContentViewShadow];
}else if(recognizer.state == UIGestureRecognizerStateChanged){
CGFloat menuVisibleWidth = self.view.bounds.size.width-self.realContentViewVisibleWidth;
CGFloat delta = self.menuHidden ? point.x/menuVisibleWidth : (menuVisibleWidth+point.x)/menuVisibleWidth;
CGFloat scale = 1-(1-MinScaleContentView)*delta;
CGFloat menuScale = MinScaleMenuView + (1-MinScaleMenuView)*delta;
if(self.menuHidden){
//以内容视图最小缩放为界限
if(scale < MinScaleContentView){//A
self.contentViewContainer.transform = CGAffineTransformMakeTranslation(menuVisibleWidth, 0);
self.contentViewContainer.transform = CGAffineTransformScale(self.contentViewContainer.transform,MinScaleContentView,MinScaleContentView);
self.contentViewScale = MinScaleContentView;
self.menuViewContainer.transform = CGAffineTransformMakeScale(1, 1);
self.menuViewContainer.transform = CGAffineTransformTranslate(self.menuViewContainer.transform, 0, 0);
}else{//大于最小界限又分大于等于1和小于1两种情况
if(scale < 1){//B
self.contentViewContainer.transform = CGAffineTransformMakeTranslation(point.x, 0);
self.contentViewContainer.transform = CGAffineTransformScale(self.contentViewContainer.transform,scale, scale);
self.contentViewScale = scale;
self.menuViewContainer.transform = CGAffineTransformMakeScale(menuScale, menuScale);
self.menuViewContainer.transform = CGAffineTransformTranslate(self.menuViewContainer.transform, -MoveDistanceMenuView *(1-delta), 0);
}else{//C
self.contentViewContainer.transform = CGAffineTransformMakeTranslation(0, 0);
self.contentViewContainer.transform = CGAffineTransformScale(self.contentViewContainer.transform,1, 1);
self.contentViewScale = 1;
self.menuViewContainer.transform = CGAffineTransformMakeScale(MinScaleMenuView, MinScaleMenuView);
self.menuViewContainer.transform = CGAffineTransformTranslate(self.menuViewContainer.transform, -MoveDistanceMenuView, 0);
}
}
}else{
if(scale > 1){//D
self.contentViewContainer.transform = CGAffineTransformMakeTranslation(0, 0);
self.contentViewContainer.transform = CGAffineTransformScale(self.contentViewContainer.transform,1,1);
self.contentViewScale = 1;
self.menuViewContainer.transform = CGAffineTransformMakeScale(MinScaleMenuView, MinScaleMenuView);
self.menuViewContainer.transform = CGAffineTransformTranslate(self.menuViewContainer.transform, -MoveDistanceMenuView, 0);
}else{
if(scale>MinScaleContentView){//E
self.contentViewContainer.transform = CGAffineTransformMakeTranslation(point.x+menuVisibleWidth, 0);
self.contentViewContainer.transform = CGAffineTransformScale(self.contentViewContainer.transform,scale, scale);
self.contentViewScale = scale;
self.menuViewContainer.transform = CGAffineTransformMakeScale(menuScale, menuScale);
self.menuViewContainer.transform = CGAffineTransformTranslate(self.menuViewContainer.transform, -MoveDistanceMenuView * (1-delta), 0);
}else{//F
self.contentViewContainer.transform =CGAffineTransformMakeTranslation(self.view.bounds.size.width-self.realContentViewVisibleWidth, 0);
self.contentViewContainer.transform = CGAffineTransformScale(self.contentViewContainer.transform,MinScaleContentView, MinScaleContentView);
self.contentViewScale = MinScaleContentView;
self.menuViewContainer.transform = CGAffineTransformMakeScale(1, 1);
self.menuViewContainer.transform = CGAffineTransformTranslate(self.menuViewContainer.transform, 0, 0);
}
}
}
}else if(recognizer.state == UIGestureRecognizerStateEnded){
[self showMenu:(self.contentViewContainer.frame.origin.x > self.view.bounds.size.width/2)];
}
}
这样的结尾是不是太不负责任了???
好吧,我提醒大家,整段代码的精华全在delta的计算,视图滑动后的最终状态是由menuVisibleWidth和MinSacleContentView来决定。根据当前手势滑动的距离占menuVisibleWidth的百分比来计算滑动动作完成度,然后根据这个值来移动和缩放相应的视图。