可能是使用的版本有点老,git上最新的变化比较大
- (void)updateTopViewHorizontalCenter:(CGFloat)newHorizontalCenter
{
CGPoint center = self.topView.center;
center.x = newHorizontalCenter;
self.topView.layer.position = center;
/* Adding by Jwt */
//NSLog(@"new center x : %f", newHorizontalCenter);
if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_6_1) {
} else {
//if (newHorizontalCenter == 160.0 || newHorizontalCenter == 480.0) {
if (newHorizontalCenter == ([[UIScreen mainScreen] bounds].size.width) / 2 || newHorizontalCenter == 480.0) {
self.topView.transform = CGAffineTransformMakeScale(1.0, 1.0);
} else {
CGFloat scale = 1 - 0.08 * ((newHorizontalCenter - 160) / 220);
self.topView.transform = CGAffineTransformMakeScale(scale, scale);
}
}
}
updateTopViewHorizontalCenter: 方法,里面写死了数值
160 是主屏幕宽度的一半
但是 480 和 220 还有 0.08 的调整,我不知道是怎么算出来
附上完整代码
//
// ECSlidingViewController.m
// ECSlidingViewController
//
// Created by Michael Enriquez on 1/23/12.
// Copyright (c) 2012 EdgeCase. All rights reserved.
//
#import "ECSlidingViewController.h"
NSString *const ECSlidingViewUnderRightWillAppear = @"ECSlidingViewUnderRightWillAppear";
NSString *const ECSlidingViewUnderLeftWillAppear = @"ECSlidingViewUnderLeftWillAppear";
NSString *const ECSlidingViewUnderLeftWillDisappear = @"ECSlidingViewUnderLeftWillDisappear";
NSString *const ECSlidingViewUnderRightWillDisappear = @"ECSlidingViewUnderRightWillDisappear";
NSString *const ECSlidingViewTopDidAnchorLeft = @"ECSlidingViewTopDidAnchorLeft";
NSString *const ECSlidingViewTopDidAnchorRight = @"ECSlidingViewTopDidAnchorRight";
NSString *const ECSlidingViewTopWillReset = @"ECSlidingViewTopWillReset";
NSString *const ECSlidingViewTopDidReset = @"ECSlidingViewTopDidReset";
@interface ECSlidingViewController()
@property (nonatomic, strong) UIView *topViewSnapshot;
@property (nonatomic, assign) CGFloat initialTouchPositionX;
@property (nonatomic, assign) CGFloat initialHoizontalCenter;
@property (nonatomic, strong) UIPanGestureRecognizer *panGesture;
@property (nonatomic, strong) UITapGestureRecognizer *resetTapGesture;
@property (nonatomic, strong) UIPanGestureRecognizer *topViewSnapshotPanGesture;
@property (nonatomic, assign) BOOL underLeftShowing;
@property (nonatomic, assign) BOOL underRightShowing;
@property (nonatomic, assign) BOOL topViewIsOffScreen;
- (NSUInteger)autoResizeToFillScreen;
- (UIView *)topView;
- (UIView *)underLeftView;
- (UIView *)underRightView;
- (void)adjustLayout;
- (void)updateTopViewHorizontalCenterWithRecognizer:(UIPanGestureRecognizer *)recognizer;
- (void)updateTopViewHorizontalCenter:(CGFloat)newHorizontalCenter;
- (void)topViewHorizontalCenterWillChange:(CGFloat)newHorizontalCenter;
- (void)topViewHorizontalCenterDidChange:(CGFloat)newHorizontalCenter;
- (void)addTopViewSnapshot;
- (void)removeTopViewSnapshot;
- (CGFloat)anchorRightTopViewCenter;
- (CGFloat)anchorLeftTopViewCenter;
- (CGFloat)resettedCenter;
- (void)underLeftWillAppear;
- (void)underRightWillAppear;
- (void)topDidReset;
- (BOOL)topViewHasFocus;
- (void)updateUnderLeftLayout;
- (void)updateUnderRightLayout;
@end
@implementation UIViewController(SlidingViewExtension)
- (ECSlidingViewController *)slidingViewController
{
UIViewController *viewController = self.parentViewController;
while (!(viewController == nil || [viewController isKindOfClass:[ECSlidingViewController class]])) {
viewController = viewController.parentViewController;
}
return (ECSlidingViewController *)viewController;
}
@end
@implementation ECSlidingViewController
// public properties
@synthesize underLeftViewController = _underLeftViewController;
@synthesize underRightViewController = _underRightViewController;
@synthesize topViewController = _topViewController;
@synthesize anchorLeftPeekAmount;
@synthesize anchorRightPeekAmount;
@synthesize anchorLeftRevealAmount;
@synthesize anchorRightRevealAmount;
@synthesize underRightWidthLayout = _underRightWidthLayout;
@synthesize underLeftWidthLayout = _underLeftWidthLayout;
@synthesize shouldAllowPanningPastAnchor;
@synthesize shouldAllowUserInteractionsWhenAnchored;
@synthesize shouldAddPanGestureRecognizerToTopViewSnapshot;
@synthesize resetStrategy = _resetStrategy;
// category properties
@synthesize topViewSnapshot;
@synthesize initialTouchPositionX;
@synthesize initialHoizontalCenter;
@synthesize panGesture = _panGesture;
@synthesize resetTapGesture;
@synthesize underLeftShowing = _underLeftShowing;
@synthesize underRightShowing = _underRightShowing;
@synthesize topViewIsOffScreen = _topViewIsOffScreen;
@synthesize topViewSnapshotPanGesture = _topViewSnapshotPanGesture;
- (void)setTopViewController:(UIViewController *)theTopViewController
{
CGRect topViewFrame = _topViewController ? _topViewController.view.frame : self.view.bounds;
[self removeTopViewSnapshot];
[_topViewController.view removeFromSuperview];
[_topViewController willMoveToParentViewController:nil];
[_topViewController removeFromParentViewController];
_topViewController = theTopViewController;
[self addChildViewController:self.topViewController];
[self.topViewController didMoveToParentViewController:self];
[_topViewController.view setAutoresizingMask:self.autoResizeToFillScreen];
[_topViewController.view setFrame:topViewFrame];
_topViewController.view.layer.shadowOffset = CGSizeZero;
_topViewController.view.layer.shadowPath = [UIBezierPath bezierPathWithRect:self.view.layer.bounds].CGPath;
[self.view addSubview:_topViewController.view];
}
- (void)setUnderLeftViewController:(UIViewController *)theUnderLeftViewController
{
[_underLeftViewController.view removeFromSuperview];
[_underLeftViewController willMoveToParentViewController:nil];
[_underLeftViewController removeFromParentViewController];
_underLeftViewController = theUnderLeftViewController;
if (_underLeftViewController) {
[self addChildViewController:self.underLeftViewController];
[self.underLeftViewController didMoveToParentViewController:self];
[self updateUnderLeftLayout];
}
}
- (void)setUnderRightViewController:(UIViewController *)theUnderRightViewController
{
[_underRightViewController.view removeFromSuperview];
[_underRightViewController willMoveToParentViewController:nil];
[_underRightViewController removeFromParentViewController];
_underRightViewController = theUnderRightViewController;
if (_underRightViewController) {
[self addChildViewController:self.underRightViewController];
[self.underRightViewController didMoveToParentViewController:self];
[self updateUnderRightLayout];
}
}
- (void)setUnderLeftWidthLayout:(ECViewWidthLayout)underLeftWidthLayout
{
if (underLeftWidthLayout == ECVariableRevealWidth && self.anchorRightPeekAmount <= 0) {
[NSException raise:@"Invalid Width Layout" format:@"anchorRightPeekAmount must be set"];
} else if (underLeftWidthLayout == ECFixedRevealWidth && self.anchorRightRevealAmount <= 0) {
[NSException raise:@"Invalid Width Layout" format:@"anchorRightRevealAmount must be set"];
}
_underLeftWidthLayout = underLeftWidthLayout;
}
- (void)setUnderRightWidthLayout:(ECViewWidthLayout)underRightWidthLayout
{
if (underRightWidthLayout == ECVariableRevealWidth && self.anchorLeftPeekAmount <= 0) {
[NSException raise:@"Invalid Width Layout" format:@"anchorLeftPeekAmount must be set"];
} else if (underRightWidthLayout == ECFixedRevealWidth && self.anchorLeftRevealAmount <= 0) {
[NSException raise:@"Invalid Width Layout" format:@"anchorLeftRevealAmount must be set"];
}
_underRightWidthLayout = underRightWidthLayout;
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.shouldAllowPanningPastAnchor = YES;
self.shouldAllowUserInteractionsWhenAnchored = NO;
self.shouldAddPanGestureRecognizerToTopViewSnapshot = NO;
self.resetTapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(resetTopView)];
_panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(updateTopViewHorizontalCenterWithRecognizer:)];
self.resetTapGesture.enabled = NO;
self.resetStrategy = ECTapping | ECPanning;
self.topViewSnapshot = [[UIView alloc] initWithFrame:self.topView.bounds];
[self.topViewSnapshot setAutoresizingMask:self.autoResizeToFillScreen];
[self.topViewSnapshot addGestureRecognizer:self.resetTapGesture];
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
self.topView.layer.shadowOffset = CGSizeZero;
self.topView.layer.shadowPath = [UIBezierPath bezierPathWithRect:self.view.layer.bounds].CGPath;
[self adjustLayout];
}
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
self.topView.layer.shadowPath = nil;
self.topView.layer.shouldRasterize = YES;
if(![self topViewHasFocus]){
[self removeTopViewSnapshot];
}
[self adjustLayout];
}
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
self.topView.layer.shadowPath = [UIBezierPath bezierPathWithRect:self.view.layer.bounds].CGPath;
self.topView.layer.shouldRasterize = NO;
if(![self topViewHasFocus]){
[self addTopViewSnapshot];
}
}
- (void)setResetStrategy:(ECResetStrategy)theResetStrategy
{
_resetStrategy = theResetStrategy;
if (_resetStrategy & ECTapping) {
self.resetTapGesture.enabled = YES;
} else {
self.resetTapGesture.enabled = NO;
}
}
- (void)adjustLayout
{
self.topViewSnapshot.frame = self.topView.bounds;
if ([self underRightShowing] && ![self topViewIsOffScreen]) {
[self updateUnderRightLayout];
[self updateTopViewHorizontalCenter:self.anchorLeftTopViewCenter];
} else if ([self underRightShowing] && [self topViewIsOffScreen]) {
[self updateUnderRightLayout];
[self updateTopViewHorizontalCenter:-self.resettedCenter];
} else if ([self underLeftShowing] && ![self topViewIsOffScreen]) {
[self updateUnderLeftLayout];
[self updateTopViewHorizontalCenter:self.anchorRightTopViewCenter];
} else if ([self underLeftShowing] && [self topViewIsOffScreen]) {
[self updateUnderLeftLayout];
[self updateTopViewHorizontalCenter:self.view.bounds.size.width + self.resettedCenter];
}
}
- (void)updateTopViewHorizontalCenterWithRecognizer:(UIPanGestureRecognizer *)recognizer
{
CGPoint currentTouchPoint = [recognizer locationInView:self.view];
CGFloat currentTouchPositionX = currentTouchPoint.x;
if (recognizer.state == UIGestureRecognizerStateBegan) {
self.initialTouchPositionX = currentTouchPositionX;
self.initialHoizontalCenter = self.topView.center.x;
} else if (recognizer.state == UIGestureRecognizerStateChanged) {
CGFloat panAmount = self.initialTouchPositionX - currentTouchPositionX;
CGFloat newCenterPosition = self.initialHoizontalCenter - panAmount;
if ((newCenterPosition < self.resettedCenter && (self.anchorLeftTopViewCenter == NSNotFound || self.underRightViewController == nil)) ||
(newCenterPosition > self.resettedCenter && (self.anchorRightTopViewCenter == NSNotFound || self.underLeftViewController == nil))) {
newCenterPosition = self.resettedCenter;
}
BOOL newCenterPositionIsOutsideAnchor = newCenterPosition < self.anchorLeftTopViewCenter || self.anchorRightTopViewCenter < newCenterPosition;
if ((newCenterPositionIsOutsideAnchor && self.shouldAllowPanningPastAnchor) || !newCenterPositionIsOutsideAnchor) {
[self topViewHorizontalCenterWillChange:newCenterPosition];
[self updateTopViewHorizontalCenter:newCenterPosition];
[self topViewHorizontalCenterDidChange:newCenterPosition];
}
} else if (recognizer.state == UIGestureRecognizerStateEnded || recognizer.state == UIGestureRecognizerStateCancelled) {
CGPoint currentVelocityPoint = [recognizer velocityInView:self.view];
CGFloat currentVelocityX = currentVelocityPoint.x;
if ([self underLeftShowing] && currentVelocityX > 100) {
[self anchorTopViewTo:ECRight];
} else if ([self underRightShowing] && currentVelocityX < 100) {
[self anchorTopViewTo:ECLeft];
} else {
[self resetTopView];
}
}
}
- (UIPanGestureRecognizer *)panGesture
{
return _panGesture;
}
- (void)anchorTopViewTo:(ECSide)side
{
[self anchorTopViewTo:side animations:nil onComplete:nil];
}
- (void)anchorTopViewTo:(ECSide)side animations:(void (^)())animations onComplete:(void (^)())complete
{
CGFloat newCenter = self.topView.center.x;
if (side == ECLeft) {
newCenter = self.anchorLeftTopViewCenter;
} else if (side == ECRight) {
newCenter = self.anchorRightTopViewCenter;
}
[self topViewHorizontalCenterWillChange:newCenter];
[UIView animateWithDuration:0.25f animations:^{
if (animations) {
animations();
}
[self updateTopViewHorizontalCenter:newCenter];
} completion:^(BOOL finished){
if (_resetStrategy & ECPanning) {
self.panGesture.enabled = YES;
} else {
self.panGesture.enabled = NO;
}
if (complete) {
complete();
}
_topViewIsOffScreen = NO;
[self addTopViewSnapshot];
dispatch_async(dispatch_get_main_queue(), ^{
NSString *key = (side == ECLeft) ? ECSlidingViewTopDidAnchorLeft : ECSlidingViewTopDidAnchorRight;
[[NSNotificationCenter defaultCenter] postNotificationName:key object:self userInfo:nil];
});
}];
}
- (void)anchorTopViewOffScreenTo:(ECSide)side
{
[self anchorTopViewOffScreenTo:side animations:nil onComplete:nil];
}
- (void)anchorTopViewOffScreenTo:(ECSide)side animations:(void(^)())animations onComplete:(void(^)())complete
{
CGFloat newCenter = self.topView.center.x;
if (side == ECLeft) {
newCenter = -self.resettedCenter;
} else if (side == ECRight) {
newCenter = self.view.bounds.size.width + self.resettedCenter;
}
[self topViewHorizontalCenterWillChange:newCenter];
[UIView animateWithDuration:0.25f animations:^{
if (animations) {
animations();
}
[self updateTopViewHorizontalCenter:newCenter];
} completion:^(BOOL finished){
if (complete) {
complete();
}
_topViewIsOffScreen = YES;
[self addTopViewSnapshot];
dispatch_async(dispatch_get_main_queue(), ^{
NSString *key = (side == ECLeft) ? ECSlidingViewTopDidAnchorLeft : ECSlidingViewTopDidAnchorRight;
[[NSNotificationCenter defaultCenter] postNotificationName:key object:self userInfo:nil];
});
}];
}
- (void)resetTopView
{
dispatch_async(dispatch_get_main_queue(), ^{
[[NSNotificationCenter defaultCenter] postNotificationName:ECSlidingViewTopWillReset object:self userInfo:nil];
});
[self resetTopViewWithAnimations:nil onComplete:nil];
}
- (void)resetTopViewWithAnimations:(void(^)())animations onComplete:(void(^)())complete
{
[self topViewHorizontalCenterWillChange:self.resettedCenter];
[UIView animateWithDuration:0.25f animations:^{
if (animations) {
animations();
}
[self updateTopViewHorizontalCenter:self.resettedCenter];
} completion:^(BOOL finished) {
if (complete) {
complete();
}
[self topViewHorizontalCenterDidChange:self.resettedCenter];
}];
}
- (NSUInteger)autoResizeToFillScreen
{
return (UIViewAutoresizingFlexibleWidth |
UIViewAutoresizingFlexibleHeight |
UIViewAutoresizingFlexibleTopMargin |
UIViewAutoresizingFlexibleBottomMargin |
UIViewAutoresizingFlexibleLeftMargin |
UIViewAutoresizingFlexibleRightMargin);
}
- (UIView *)topView
{
return self.topViewController.view;
}
- (UIView *)underLeftView
{
return self.underLeftViewController.view;
}
- (UIView *)underRightView
{
return self.underRightViewController.view;
}
- (void)updateTopViewHorizontalCenter:(CGFloat)newHorizontalCenter
{
CGPoint center = self.topView.center;
center.x = newHorizontalCenter;
self.topView.layer.position = center;
/* Adding by Jwt */
//NSLog(@"new center x : %f", newHorizontalCenter);
if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_6_1) {
} else {
//if (newHorizontalCenter == 160.0 || newHorizontalCenter == 480.0) {
if (newHorizontalCenter == ([[UIScreen mainScreen] bounds].size.width) / 2 || newHorizontalCenter == 480.0) {
self.topView.transform = CGAffineTransformMakeScale(1.0, 1.0);
} else {
CGFloat scale = 1 - 0.08 * ((newHorizontalCenter - 160) / 220);
self.topView.transform = CGAffineTransformMakeScale(scale, scale);
}
}
}
- (void)topViewHorizontalCenterWillChange:(CGFloat)newHorizontalCenter
{
CGPoint center = self.topView.center;
if (center.x >= self.resettedCenter && newHorizontalCenter == self.resettedCenter) {
dispatch_async(dispatch_get_main_queue(), ^{
[[NSNotificationCenter defaultCenter] postNotificationName:ECSlidingViewUnderLeftWillDisappear object:self userInfo:nil];
});
}
if (center.x <= self.resettedCenter && newHorizontalCenter == self.resettedCenter) {
dispatch_async(dispatch_get_main_queue(), ^{
[[NSNotificationCenter defaultCenter] postNotificationName:ECSlidingViewUnderRightWillDisappear object:self userInfo:nil];
});
}
if (center.x <= self.resettedCenter && newHorizontalCenter > self.resettedCenter) {
[self underLeftWillAppear];
} else if (center.x >= self.resettedCenter && newHorizontalCenter < self.resettedCenter) {
[self underRightWillAppear];
}
}
- (void)topViewHorizontalCenterDidChange:(CGFloat)newHorizontalCenter
{
if (newHorizontalCenter == self.resettedCenter) {
[self topDidReset];
}
}
- (void)addTopViewSnapshot
{
if (!self.topViewSnapshot.superview && !self.shouldAllowUserInteractionsWhenAnchored) {
topViewSnapshot.layer.contents = (id)[UIImage imageWithUIView:self.topView].CGImage;
if (self.shouldAddPanGestureRecognizerToTopViewSnapshot && (_resetStrategy & ECPanning)) {
if (!_topViewSnapshotPanGesture) {
_topViewSnapshotPanGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(updateTopViewHorizontalCenterWithRecognizer:)];
}
[topViewSnapshot addGestureRecognizer:_topViewSnapshotPanGesture];
}
[self.topView addSubview:self.topViewSnapshot];
}
}
- (void)removeTopViewSnapshot
{
if (self.topViewSnapshot.superview) {
[self.topViewSnapshot removeFromSuperview];
}
}
- (CGFloat)anchorRightTopViewCenter
{
if (self.anchorRightPeekAmount) {
return self.view.bounds.size.width + self.resettedCenter - self.anchorRightPeekAmount;
} else if (self.anchorRightRevealAmount) {
return self.resettedCenter + self.anchorRightRevealAmount;
} else {
return NSNotFound;
}
}
- (CGFloat)anchorLeftTopViewCenter
{
if (self.anchorLeftPeekAmount) {
return -self.resettedCenter + self.anchorLeftPeekAmount;
} else if (self.anchorLeftRevealAmount) {
return -self.resettedCenter + (self.view.bounds.size.width - self.anchorLeftRevealAmount);
} else {
return NSNotFound;
}
}
- (CGFloat)resettedCenter
{
return (self.view.bounds.size.width / 2);
}
- (void)underLeftWillAppear
{
dispatch_async(dispatch_get_main_queue(), ^{
[[NSNotificationCenter defaultCenter] postNotificationName:ECSlidingViewUnderLeftWillAppear object:self userInfo:nil];
});
[self.underRightView removeFromSuperview];
[self updateUnderLeftLayout];
[self.view insertSubview:self.underLeftView belowSubview:self.topView];
_underLeftShowing = YES;
_underRightShowing = NO;
}
- (void)underRightWillAppear
{
dispatch_async(dispatch_get_main_queue(), ^{
[[NSNotificationCenter defaultCenter] postNotificationName:ECSlidingViewUnderRightWillAppear object:self userInfo:nil];
});
[self.underLeftView removeFromSuperview];
[self updateUnderRightLayout];
[self.view insertSubview:self.underRightView belowSubview:self.topView];
_underLeftShowing = NO;
_underRightShowing = YES;
}
- (void)topDidReset
{
dispatch_async(dispatch_get_main_queue(), ^{
[[NSNotificationCenter defaultCenter] postNotificationName:ECSlidingViewTopDidReset object:self userInfo:nil];
});
[self.topView removeGestureRecognizer:self.resetTapGesture];
[self removeTopViewSnapshot];
self.panGesture.enabled = YES;
[self.underRightView removeFromSuperview];
[self.underLeftView removeFromSuperview];
_underLeftShowing = NO;
_underRightShowing = NO;
_topViewIsOffScreen = NO;
}
- (BOOL)topViewHasFocus
{
return !_underLeftShowing && !_underRightShowing && !_topViewIsOffScreen;
}
- (void)updateUnderLeftLayout
{
if (self.underLeftWidthLayout == ECFullWidth) {
[self.underLeftView setAutoresizingMask:self.autoResizeToFillScreen];
[self.underLeftView setFrame:self.view.bounds];
} else if (self.underLeftWidthLayout == ECVariableRevealWidth && !self.topViewIsOffScreen) {
CGRect frame = self.view.bounds;
frame.size.width = frame.size.width - self.anchorRightPeekAmount;
self.underLeftView.frame = frame;
} else if (self.underLeftWidthLayout == ECFixedRevealWidth) {
CGRect frame = self.view.bounds;
frame.size.width = self.anchorRightRevealAmount;
self.underLeftView.frame = frame;
} else {
[NSException raise:@"Invalid Width Layout" format:@"underLeftWidthLayout must be a valid ECViewWidthLayout"];
}
}
- (void)updateUnderRightLayout
{
if (self.underRightWidthLayout == ECFullWidth) {
[self.underRightViewController.view setAutoresizingMask:self.autoResizeToFillScreen];
self.underRightView.frame = self.view.bounds;
} else if (self.underRightWidthLayout == ECVariableRevealWidth) {
CGRect frame = self.view.bounds;
CGFloat newLeftEdge;
CGFloat newWidth = frame.size.width;
if (self.topViewIsOffScreen) {
newLeftEdge = 0;
} else {
newLeftEdge = self.anchorLeftPeekAmount;
newWidth -= self.anchorLeftPeekAmount;
}
frame.origin.x = newLeftEdge;
frame.size.width = newWidth;
self.underRightView.frame = frame;
} else if (self.underRightWidthLayout == ECFixedRevealWidth) {
CGRect frame = self.view.bounds;
CGFloat newLeftEdge = frame.size.width - self.anchorLeftRevealAmount;
CGFloat newWidth = self.anchorLeftRevealAmount;
frame.origin.x = newLeftEdge;
frame.size.width = newWidth;
self.underRightView.frame = frame;
} else {
[NSException raise:@"Invalid Width Layout" format:@"underRightWidthLayout must be a valid ECViewWidthLayout"];
}
}
@end
人生最曼妙的风景,竟是内心的淡定与从容!