YRSideViewController.m 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365
  1. //
  2. // YRSideViewController.m
  3. // YRSnippets
  4. //
  5. // Created by 王晓宇 on 14-5-10.
  6. // Copyright (c) 2014年 王晓宇. All rights reserved.
  7. //
  8. #import "YRSideViewController.h"
  9. #import "MyUINavigationController.h"
  10. @interface YRSideViewController ()<UIGestureRecognizerDelegate>{
  11. UIView *_baseView;//目前是_baseView
  12. UIView *_currentView;//其实就是rootViewController.view
  13. UIPanGestureRecognizer *_panGestureRecognizer;
  14. CGPoint _startPanPoint;
  15. CGPoint _lastPanPoint;
  16. BOOL _panMovingRightOrLeft;//true是向右,false是向左
  17. UIButton *_coverButton;
  18. BOOL _isInit;//是否是初始化
  19. }
  20. @end
  21. @implementation YRSideViewController
  22. - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
  23. {
  24. self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
  25. if (self) {
  26. // Custom initialization
  27. _leftViewShowWidth = 267;
  28. _rightViewShowWidth = 267;
  29. _animationDuration = 0.35;
  30. _showBoundsShadow = true;
  31. _panGestureRecognizer = [[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(pan:)];
  32. [_panGestureRecognizer setDelegate:self];
  33. _panMovingRightOrLeft = false;
  34. _lastPanPoint = CGPointZero;
  35. _coverButton = [[UIButton alloc]initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)];
  36. [_coverButton addTarget:self action:@selector(hideSideViewController) forControlEvents:UIControlEventTouchUpInside];
  37. _isInit = true;
  38. }
  39. return self;
  40. }
  41. - (id)init{
  42. self = [super init];
  43. if (self) {
  44. LeftViewController *vc=[[LeftViewController alloc]init];
  45. vc.view.backgroundColor=[UIColor whiteColor];
  46. MyUINavigationController* nav = [[MyUINavigationController alloc] initWithRootViewController:vc];
  47. self.leftViewController=nav;
  48. }
  49. return self;
  50. }
  51. - (void)viewDidLoad
  52. {
  53. [super viewDidLoad];
  54. // self.navigationController.navigationBar.translucent = YES;
  55. self.leftViewShowWidth=kLeftViewWid;
  56. //动画效果可以被自己自定义,具体请看api
  57. [self setRootViewMoveBlock:^(UIView *rootView, CGRect orginFrame, CGFloat xoffset) {
  58. //使用简单的平移动画
  59. rootView.frame=CGRectMake(xoffset, orginFrame.origin.y, orginFrame.size.width, orginFrame.size.height);
  60. }];
  61. // Do any additional setup after loading the view.
  62. _baseView = self.view;
  63. [_baseView setBackgroundColor:[UIColor whiteColor]];
  64. }
  65. - (void)viewWillAppear:(BOOL)animated{
  66. [super viewWillAppear:animated];
  67. self.navigationController.navigationBarHidden = YES;
  68. if (!self.rootViewController) {
  69. NSAssert(false, @"you must set rootViewController!!");
  70. }
  71. if (_isInit) {
  72. [self resetCurrentViewToRootViewController];
  73. _isInit=false;
  74. }
  75. }
  76. - (void)didReceiveMemoryWarning
  77. {
  78. [super didReceiveMemoryWarning];
  79. // Dispose of any resources that can be recreated.
  80. }
  81. - (void)setRootViewController:(UIViewController *)rootViewController{
  82. if (_rootViewController!=rootViewController) {
  83. if (_rootViewController) {
  84. [_rootViewController removeFromParentViewController];
  85. }
  86. _rootViewController=rootViewController;
  87. if (_rootViewController) {
  88. [self addChildViewController:_rootViewController];
  89. }
  90. if (!_isInit) {
  91. NSLog(@"!_isInit");
  92. // [self resetCurrentViewToRootViewController];
  93. }
  94. }
  95. }
  96. -(void)setLeftViewController:(UIViewController *)leftViewController{
  97. if (_leftViewController!=leftViewController) {
  98. if (_leftViewController) {
  99. [_leftViewController removeFromParentViewController];
  100. }
  101. _leftViewController=leftViewController;
  102. if (_leftViewController) {
  103. [self addChildViewController:_leftViewController];
  104. }
  105. }
  106. }
  107. -(void)setRightViewController:(UIViewController *)rightViewController{
  108. if (_rightViewController!=rightViewController) {
  109. if (_rightViewController) {
  110. [_rightViewController removeFromParentViewController];
  111. }
  112. _rightViewController=rightViewController;
  113. if (_rightViewController) {
  114. [self addChildViewController:_rightViewController];
  115. }
  116. }
  117. }
  118. - (void)setNeedSwipeShowMenu:(BOOL)needSwipeShowMenu{
  119. _needSwipeShowMenu = needSwipeShowMenu;
  120. if (needSwipeShowMenu) {
  121. [_baseView addGestureRecognizer:_panGestureRecognizer];
  122. }else{
  123. [_baseView removeGestureRecognizer:_panGestureRecognizer];
  124. }
  125. }
  126. - (void)showShadow:(BOOL)show{
  127. _currentView.layer.shadowOpacity = show ? 0.8f : 0.0f;
  128. if (show) {
  129. _currentView.layer.cornerRadius = 4.0f;
  130. _currentView.layer.shadowOffset = CGSizeZero;
  131. _currentView.layer.shadowRadius = 4.0f;
  132. _currentView.layer.shadowPath = [UIBezierPath bezierPathWithRect:_currentView.bounds].CGPath;
  133. }
  134. }
  135. -(void)resetCurrentViewToRootViewController{
  136. if (_currentView!=_rootViewController.view) {
  137. CGRect frame = CGRectZero;
  138. CGAffineTransform transform = CGAffineTransformIdentity;
  139. if (!_currentView) {
  140. frame = _baseView.bounds;
  141. }else{
  142. frame=_currentView.frame;
  143. transform = _currentView.transform;
  144. }
  145. [_currentView removeFromSuperview];
  146. _currentView = _rootViewController.view;
  147. [_baseView addSubview:_currentView];
  148. _currentView.transform=transform;
  149. _currentView.frame = frame;
  150. if (_leftViewController.view.superview||_rightViewController.view.superview) {
  151. [_currentView addSubview:_coverButton];
  152. [self showShadow:_showBoundsShadow];
  153. }
  154. }
  155. }
  156. #pragma mark ShowOrHideTheView
  157. - (void)willShowLeftViewController{
  158. if (!_leftViewController || _leftViewController.view.superview) {
  159. return;
  160. }
  161. _leftViewController.view.frame=_baseView.bounds;
  162. [_baseView insertSubview:_leftViewController.view belowSubview:_currentView];
  163. if (_rightViewController && _rightViewController.view.superview) {
  164. [_rightViewController.view removeFromSuperview];
  165. }
  166. }
  167. - (void)willShowRightViewController{
  168. if (!_rightViewController || _rightViewController.view.superview) {
  169. return;
  170. }
  171. _rightViewController.view.frame=_baseView.bounds;
  172. [_baseView insertSubview:_rightViewController.view belowSubview:_currentView];
  173. if (_leftViewController && _leftViewController.view.superview) {
  174. [_leftViewController.view removeFromSuperview];
  175. }
  176. }
  177. - (void)showLeftViewController:(BOOL)animated{
  178. if (!_leftViewController) {
  179. return;
  180. }
  181. [self willShowLeftViewController];
  182. NSTimeInterval animatedTime=0;
  183. if (animated) {
  184. animatedTime = ABS(_leftViewShowWidth - _currentView.frame.origin.x) / _leftViewShowWidth * _animationDuration;
  185. }
  186. [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
  187. [UIView animateWithDuration:animatedTime animations:^{
  188. [self layoutCurrentViewWithOffset:_leftViewShowWidth];
  189. [_currentView addSubview:_coverButton];
  190. [self showShadow:_showBoundsShadow];
  191. }];
  192. }
  193. - (void)showRightViewController:(BOOL)animated{
  194. if (!_rightViewController) {
  195. return;
  196. }
  197. [self willShowRightViewController];
  198. NSTimeInterval animatedTime = 0;
  199. if (animated) {
  200. animatedTime = ABS(_rightViewShowWidth + _currentView.frame.origin.x) / _rightViewShowWidth * _animationDuration;
  201. }
  202. [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
  203. [UIView animateWithDuration:animatedTime animations:^{
  204. [self layoutCurrentViewWithOffset:-_rightViewShowWidth];
  205. [_currentView addSubview:_coverButton];
  206. [self showShadow:_showBoundsShadow];
  207. }];
  208. }
  209. - (void)hideSideViewController:(BOOL)animated{
  210. [self showShadow:false];
  211. NSTimeInterval animatedTime = 0;
  212. if (animated) {
  213. animatedTime = ABS(_currentView.frame.origin.x / (_currentView.frame.origin.x>0?_leftViewShowWidth:_rightViewShowWidth)) * _animationDuration;
  214. }
  215. [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
  216. [UIView animateWithDuration:animatedTime animations:^{
  217. [self layoutCurrentViewWithOffset:0];
  218. } completion:^(BOOL finished) {
  219. [_coverButton removeFromSuperview];
  220. [_leftViewController.view removeFromSuperview];
  221. [_rightViewController.view removeFromSuperview];
  222. }];
  223. }
  224. - (void)hideSideViewController{
  225. [self hideSideViewController:true];
  226. }
  227. #pragma mark UIGestureRecognizerDelegate
  228. - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
  229. // Check for horizontal pan gesture
  230. if (gestureRecognizer == _panGestureRecognizer) {
  231. UIPanGestureRecognizer *panGesture = (UIPanGestureRecognizer*)gestureRecognizer;
  232. CGPoint translation = [panGesture translationInView:_baseView];
  233. if ([panGesture velocityInView:_baseView].x < 600 && ABS(translation.x)/ABS(translation.y)>1) {
  234. return YES;
  235. }
  236. return NO;
  237. }
  238. return YES;
  239. }
  240. - (void)pan:(UIPanGestureRecognizer*)pan{
  241. if (_panGestureRecognizer.state==UIGestureRecognizerStateBegan) {
  242. _startPanPoint=_currentView.frame.origin;
  243. if (_currentView.frame.origin.x==0) {
  244. [self showShadow:_showBoundsShadow];
  245. }
  246. CGPoint velocity=[pan velocityInView:_baseView];
  247. if(velocity.x>0){
  248. if (_currentView.frame.origin.x>=0 && _leftViewController && !_leftViewController.view.superview) {
  249. [self willShowLeftViewController];
  250. }
  251. }else if (velocity.x<0) {
  252. if (_currentView.frame.origin.x<=0 && _rightViewController && !_rightViewController.view.superview) {
  253. [self willShowRightViewController];
  254. }
  255. }
  256. return;
  257. }
  258. CGPoint currentPostion = [pan translationInView:_baseView];
  259. CGFloat xoffset = _startPanPoint.x + currentPostion.x;
  260. if (xoffset>0) {//向右滑
  261. if (_leftViewController && _leftViewController.view.superview) {
  262. xoffset = xoffset>_leftViewShowWidth?_leftViewShowWidth:xoffset;
  263. }else{
  264. xoffset = 0;
  265. }
  266. }else if(xoffset<0){//向左滑
  267. if (_rightViewController && _rightViewController.view.superview) {
  268. xoffset = xoffset<-_rightViewShowWidth?-_rightViewShowWidth:xoffset;
  269. }else{
  270. xoffset = 0;
  271. }
  272. }
  273. if (xoffset!=_currentView.frame.origin.x) {
  274. [self layoutCurrentViewWithOffset:xoffset];
  275. }
  276. if (_panGestureRecognizer.state==UIGestureRecognizerStateEnded) {
  277. if (_currentView.frame.origin.x==0) {
  278. [self showShadow:false];
  279. }else{
  280. if (_panMovingRightOrLeft && _currentView.frame.origin.x>20) {
  281. [self showLeftViewController:true];
  282. }else if(!_panMovingRightOrLeft && _currentView.frame.origin.x<-20){
  283. [self showRightViewController:true];
  284. }else{
  285. [self hideSideViewController];
  286. }
  287. }
  288. _lastPanPoint = CGPointZero;
  289. }else{
  290. CGPoint velocity = [pan velocityInView:_baseView];
  291. if (velocity.x>0) {
  292. _panMovingRightOrLeft = true;
  293. }else if(velocity.x<0){
  294. _panMovingRightOrLeft = false;
  295. }
  296. }
  297. }
  298. //重写此方法可以改变动画效果,PS._currentView就是RootViewController.view
  299. - (void)layoutCurrentViewWithOffset:(CGFloat)xoffset{
  300. if (_showBoundsShadow) {
  301. _currentView.layer.shadowPath = [UIBezierPath bezierPathWithRect:_currentView.bounds].CGPath;
  302. }
  303. if (self.rootViewMoveBlock) {//如果有自定义动画,使用自定义的效果
  304. self.rootViewMoveBlock(_currentView,_baseView.bounds,xoffset);
  305. return;
  306. }
  307. /*平移的动画
  308. [_currentView setFrame:CGRectMake(xoffset, _baseView.bounds.origin.y, _baseView.frame.size.width, _baseView.frame.size.height)];
  309. return;
  310. //*/
  311. // /*平移带缩放效果的动画
  312. static CGFloat h2w = 0;
  313. if (h2w==0) {
  314. h2w = _baseView.frame.size.height/_baseView.frame.size.width;
  315. }
  316. CGFloat scale = ABS(600 - ABS(xoffset)) / 600;
  317. scale = MAX(0.8, scale);
  318. _currentView.transform = CGAffineTransformMakeScale(scale, scale);
  319. CGFloat totalWidth=_baseView.frame.size.width;
  320. CGFloat totalHeight=_baseView.frame.size.height;
  321. if (UIInterfaceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation])) {
  322. totalHeight=_baseView.frame.size.width;
  323. totalWidth=_baseView.frame.size.height;
  324. }
  325. if (xoffset>0) {//向右滑的
  326. [_currentView setFrame:CGRectMake(xoffset, _baseView.bounds.origin.y + (totalHeight * (1 - scale) / 2), totalWidth * scale, totalHeight * scale)];
  327. }else{//向左滑的
  328. [_currentView setFrame:CGRectMake(_baseView.frame.size.width * (1 - scale) + xoffset, _baseView.bounds.origin.y + (totalHeight*(1 - scale) / 2), totalWidth * scale, totalHeight * scale)];
  329. }
  330. }
  331. @end