使用ICSDrawerController 实现侧滑功能
在ICSDrawerController 第三方上做了修改实现,QQ 点击头像打开关抽屉头像渐变的效果
- (void)hiddenHeadView:(hiddenHeadViewBlock)block;
@property(nonatomic,copy) hiddenHeadViewBlock hiddenBlock;
- (void)hiddenHeadView:(hiddenHeadViewBlock)block { self.hiddenBlock = block; }
在拖拽滑动的手势方法中监听滑动的方法中来改变透明度
- (void)panGestureRecognized:(UIPanGestureRecognizer *)panGestureRecognizer { NSParameterAssert(self.leftView); NSParameterAssert(self.centerView); UIGestureRecognizerState state = panGestureRecognizer.state; CGPoint location = [panGestureRecognizer locationInView:self.view]; CGPoint velocity = [panGestureRecognizer velocityInView:self.view]; switch (state) { case UIGestureRecognizerStateBegan: self.panGestureStartLocation = location;//记录当前的位置 if (self.drawerState == ICSDrawerControllerStateClosed) { [self willOpen]; } else { [self willClose]; } break; case UIGestureRecognizerStateChanged: { //每次拖拽滑动 CGFloat delta = 0.0f; if (self.drawerState == ICSDrawerControllerStateOpening) { delta = location.x - self.panGestureStartLocation.x; } else if (self.drawerState == ICSDrawerControllerStateClosing) { delta = kICSDrawerControllerDrawerDepth - (self.panGestureStartLocation.x - location.x); } CGRect l = self.leftView.frame; CGRect c = self.centerView.frame; if (delta > kICSDrawerControllerDrawerDepth) { l.origin.x = 0.0f; c.origin.x = kICSDrawerControllerDrawerDepth; } else if (delta < 0.0f) { l.origin.x = kICSDrawerControllerLeftViewInitialOffset; c.origin.x = 0.0f; } else { // While the centerView can move up to kICSDrawerControllerDrawerDepth points, to achieve a parallax effect // the leftView has move no more than kICSDrawerControllerLeftViewInitialOffset points l.origin.x = kICSDrawerControllerLeftViewInitialOffset - (delta * kICSDrawerControllerLeftViewInitialOffset) / kICSDrawerControllerDrawerDepth; c.origin.x = delta; CGFloat alpha = 1 - delta/100/2.6; if (alpha > 1.0) { alpha = 1.0; }else if(alpha < 0){ alpha = 0; } //头像是否显示隐藏 self.hiddenBlock(alpha); } self.leftView.frame = l; self.centerView.frame = c; break; } case UIGestureRecognizerStateEnded: { //拖拽结束 if (self.drawerState == ICSDrawerControllerStateOpening) { CGFloat centerViewLocation = self.centerView.frame.origin.x; if (centerViewLocation == kICSDrawerControllerDrawerDepth) { // Open the drawer without animation, as it has already being dragged in its final position [self setNeedsStatusBarAppearanceUpdate]; [self didOpen]; } else if (centerViewLocation > self.view.bounds.size.width / 3 && velocity.x > 0.0f) { // Animate the drawer opening [self animateOpening]; } else { // Animate the drawer closing, as the opening gesture hasn't been completed or it has // been reverted by the user [self didOpen]; [self willClose]; [self animateClosing]; } } else if (self.drawerState == ICSDrawerControllerStateClosing) { CGFloat centerViewLocation = self.centerView.frame.origin.x; if (centerViewLocation == 0.0f) { // Close the drawer without animation, as it has already being dragged in its final position [self setNeedsStatusBarAppearanceUpdate]; [self didClose]; } else if (centerViewLocation < (2 * self.view.bounds.size.width) / 3 && velocity.x < 0.0f) { // Animate the drawer closing [self animateClosing]; } else { // Animate the drawer opening, as the opening gesture hasn't been completed or it has // been reverted by the user [self didClose]; // Here we save the current position for the leftView since // we want the opening animation to start from the current position // and not the one that is set in 'willOpen' CGRect l = self.leftView.frame; [self willOpen]; self.leftView.frame = l; [self animateOpening]; } } } break; default: break; } } #pragma mark - Animations #pragma mark Opening animation - (void)animateOpening { NSParameterAssert(self.drawerState == ICSDrawerControllerStateOpening); NSParameterAssert(self.leftView); NSParameterAssert(self.centerView); // Calculate the final frames for the container views CGRect leftViewFinalFrame = self.view.bounds; CGRect centerViewFinalFrame = self.view.bounds; centerViewFinalFrame.origin.x = kICSDrawerControllerDrawerDepth; [UIView animateWithDuration:kICSDrawerControllerAnimationDuration delay:0 usingSpringWithDamping:kICSDrawerControllerOpeningAnimationSpringDamping initialSpringVelocity:kICSDrawerControllerOpeningAnimationSpringInitialVelocity options:UIViewAnimationOptionCurveLinear animations:^{ self.centerView.frame = centerViewFinalFrame; self.leftView.frame = leftViewFinalFrame; self.hiddenBlock(0); [self setNeedsStatusBarAppearanceUpdate]; } completion:^(BOOL finished) { [self didOpen]; }]; } #pragma mark Closing animation - (void)animateClosing { NSParameterAssert(self.drawerState == ICSDrawerControllerStateClosing); NSParameterAssert(self.leftView); NSParameterAssert(self.centerView); // Calculate final frames for the container views CGRect leftViewFinalFrame = self.leftView.frame; leftViewFinalFrame.origin.x = kICSDrawerControllerLeftViewInitialOffset; CGRect centerViewFinalFrame = self.view.bounds; [UIView animateWithDuration:kICSDrawerControllerAnimationDuration delay:0 usingSpringWithDamping:kICSDrawerControllerClosingAnimationSpringDamping initialSpringVelocity:kICSDrawerControllerClosingAnimationSpringInitialVelocity options:UIViewAnimationOptionCurveLinear animations:^{ self.centerView.frame = centerViewFinalFrame; self.leftView.frame = leftViewFinalFrame; self.hiddenBlock(1); [self setNeedsStatusBarAppearanceUpdate]; } completion:^(BOOL finished) { [self didClose]; }]; }
给当前类扩充一个方法,拿到当前conroller的menuController
@interface UIViewController (ICSDrawerController) //拿到当前conroller的menuController //如果不存在,返回nil @property (nonatomic, readonly) ICSDrawerController* menuController; @end
@implementation UIViewController (ICSDrawerController) - (ICSDrawerController *)menuController { if (self.parentViewController == nil) { return nil; }else if ([self.parentViewController isKindOfClass:[ICSDrawerController class]]) { return (ICSDrawerController* )self.parentViewController; }else { return self.parentViewController.menuController; } } @end
换皮肤功能使用 KVO 监听属性就可以实现,这里附上代码https://github.com/SummerHH/QQMenu