在做过的几个项目之中,经常会需要用到类似于qq一样的侧滑栏,网上也有许多框架能够实现这样的功能,但是有时候我们的需求效果却不仅是“抽屉”,左右边的界面滑动,中间界面被遮住的需求也是需要的。按照这种需求,我仿照着第三方卡框架的实现原理做了这个跟我耦合性较高的侧滑栏。
侧滑一般是使用的容器性的视图控制器,也就是说在这个容器类中我可以添加几个视图控制器,并取得控制器中得view按照你编辑的规则显示在当前控制器之上。当然我的侧滑栏的实现也采取了这一原理。 但是,还有一个问题就是当你在做类似的侧边栏的时候,你想要你所有的界面都能够通过的侧滑的手势获取到你的侧滑栏的话。有时候却往往不能得到你想要的效果,我所采取的解决方法是可以保障在同一导航树下的所有视图都能都获取侧滑的功能,就是将你自定义的容器类的子集控制器直接给你所创建的导航栏控制器。这样当前导航器的导航树下面的所有界面都能够实现侧滑的功能了。
我实现侧滑的功能共使用了四个控制语句其中2个是大部分调用策划功能的关键方法。分别是2个手势所绑定的即时滑动的事件和2个自由的实例方法。其中手势方法是基于pan拖拽事件之上,能够实时的检测到你手指的滑动距离和滑动速度,从而能够实时的随手指的操作进行滑动操作具体的方法如下:
- (void)pan:(UIPanGestureRecognizer *)pan{
//<span style="font-family: Arial, Helvetica, sans-serif;">[pan translationInView:_rootViewController.view];方法能否获取你在你指定的界面上的移动点的状态,通过取.x和.y获取在x轴和y轴的位移。</span>
//<span style="font-family: Arial, Helvetica, sans-serif;">[pan velocityInView:self.view];方法则能获取在你指定界面上的手势速度,当然也分为x轴上的移动速度和y轴上的移动速度。</span>
CGPoint translation = [pan translationInView:_rootViewController.view];
CGPoint velocity = [pan velocityInView:self.view];
offsets = translation.x;
// if (startPoints >= 0&& startPoints <=50) 这行语句是用来定义你滑动区域的,starPoint可以用touch事件的begin来得到。
{
if (translation.x > 0) {
[self showLeftViewController:YES];
}
if (pan.state == UIGestureRecognizerStateEnded) {
if (translation.x >=140) {
[self leftPull];
}else {
if (velocity.x > 500) {
[self leftPull];
}else{
[self rightPull];
}
}
} ,
同时,我们要注意在这个方法里面,包含了手势的几个状态(当然这里所提及的时连串手势的状态)单独手势的状态将会在后面补充。
1.UIGestureRecognizerStatePossible
2.UIGestureRecognizerStateBegan
3.UIGestureRecognizerStateChanged
4.UIGestureRecognizerStateEnded
5.UIGestureRecognizerStateFailed这五个状态其实就是一个类似的状态机,在possbile的状态下有可能是failed状态和began状态,如果获取的时began状态则会继续触发后面的手势change状态和结束Ended状态。所以一个简单的手势并不是如何很简单的只是一个手势而已,利用好其中的每个环节都能够很好的便于我们进行开发。我在程序中就是用了当你的手势操作结束之后的那种方法,用来判定当你手势结束之后我的侧滑栏的最终位置应该在哪个地方。同时再次调用我们定义好的实例方法。
- (void)leftPull{
[self showLeftViewController:YES];
[self willShowLeftViewController];
[UIView animateKeyframesWithDuration:0.6 delay:0 options:UIViewKeyframeAnimationOptionLayoutSubviews animations:^{
_leftViewController.view.frame = CGRectMake(0, 20, SCREEN_WIDTH-50, self.view.bounds.size.height-20);
_coverButton.alpha = 0.7;
} completion:nil];
}
在block块中实现页面的侧滑,改变frame的动画。
当然前面我们就讲过界面的切换,其实就是将显示在同一baseView上的不同的view的切换,remove你不望显示的界面,
addsubview或者insertView你想要显示的view,所以每当你要滑动一个页面进当显示的范围的话,就要提前做一个显示
环境的清理,如下图:
- (void)showLeftViewController:(BOOL)animated{
// 如果不是左边的控制器的话,返回
if (!_leftViewController) {
return;
}
// 首先调用将要显示的方法,获取页面
if (animated == YES) {
[self willShowLeftViewController];
[_baseView insertSubview:_coverButton belowSubview:_leftViewController.view];
_coverButton.alpha = 0;
[_leftViewController.view setFrame:CGRectMake(-SCREEN_WIDTH + 50 + offsets, 20, SCREEN_WIDTH - 50, SCREEN_HEIGHT-20)];
double alph = offsets/(SCREEN_WIDTH*1.5);
_coverButton.alpha = alph;
}
}
大概思路就是这样,当然这样做出来的界面效果功能并不是很完善,改进之后再更新吧。