更好的抽屉效果(ios)
昨天项目基本没啥事了,晚上早早的就回家了,躺在床上无聊地玩着手机(Android的),在清理系统垃圾时被一个“360手机助手”给吸引了,
其实我是被它的那个抽屉效果给吸引了,此时你也许会觉得我out了 ,一个抽屉效果有啥好吸引人的。
以前在项目中我也用到过抽屉,也看过大量的抽屉效果,大部分时间时只有一个view可以滑动的,下面那个view是不动的,就像是拉出或推出一个view的效果差不多,
但看到这个 360手机助手的抽屉效果时,我觉得原来的那些真没这个好看。在这个程序中,当你左右拖动那个view A时,另外一个view B也会相应的滑动,但滑动的幅度没有你拖动的那个view A大,不知道我表达清楚没有,你可以下载个360手机助手看看。
于是今天就模仿了一下,拖动view A时 两个view都可以滑动,则说明动画时作用两个view的。
下面直接上代码吧,代码很简单,也没具体完善逻辑,只是个简单的效果实现 ,了解抽屉效果的很容易就看懂的
1.工程结构图
2.主要的代码
// // Drawer.h // SlideDrawer // // Created by PSH_Chen_Tao on 10/12/13. // Copyright (c) 2013 wolfman. All rights reserved. // #import <UIKit/UIKit.h> //表明当前状态的枚举常量 typedef enum{ DrawerStatusLeft, DrawerStatusRight }DrawerStatus; @interface Drawer : UIView //初始化方法 -(id)initWithParent:(UIViewController *)parentViewController firstContent:(UIViewController *)firstContentViewController secondContent:(UIViewController *)secondContentViewController; @end
1 // 2 // Drawer.m 3 // SlideDrawer 4 // 5 // Created by PSH_Chen_Tao on 10/12/13. 6 // Copyright (c) 2013 wolfman. All rights reserved. 7 // 8 9 #import "Drawer.h" 10 #define kDistance 50 11 //#define firstContentMoveDistance 100 12 @implementation Drawer{ 13 UIViewController *parent; 14 15 //控制第一个内容view的controller 16 UIViewController *firstContent; 17 //控制第二个内容view的controller 18 UIViewController *secondContent; 19 20 21 // 左滑时 firstContent的 view的center 22 CGPoint firstLeft; 23 // 右滑时 firstContent的 view的center 24 CGPoint firstRight; 25 26 // 左滑时 secondContent的 view的center 27 CGPoint secondLeft; 28 // 右滑时 secondContent的 view的center 29 CGPoint secondRight; 30 31 // 目前的状态 32 DrawerStatus status; 33 34 // firstContent 的 center 35 CGPoint firstContentCenter; 36 37 38 //移动比列,这个是关键,本程序是类似360手机助手一样的效果,两边的view都是 39 //可同时移动的,在此就需要一个很好的匹配,移动时两个view的间距不能增大或减小 40 float moveScale; 41 } 42 43 44 -(id)initWithParent:(UIViewController *)parentViewController firstContent:(UIViewController *)firstContentViewController secondContent:(UIViewController *)secondContentViewController{ 45 parent = parentViewController; 46 firstContent = firstContentViewController; 47 secondContent = secondContentViewController; 48 // 为了便于效果查看 49 firstContent.view.backgroundColor = [UIColor redColor]; 50 secondContent.view.backgroundColor = [UIColor greenColor]; 51 52 //设置frame 53 self = [super initWithFrame:CGRectMake(0, 0, parent.view.frame.size.width, parent.view.frame.size.height)]; 54 if (self) { 55 firstContent.view.frame = CGRectMake(0, 0, self.frame.size.width, parent.view.frame.size.height); 56 [self addSubview:firstContent.view]; 57 secondContent.view.frame = CGRectMake(0, 0, parent.view.frame.size.width, parent.view.frame.size.height); 58 [self addSubview:secondContent.view]; 59 60 // 下面算firstContent 和 secondContent的左右中心点时是要遵循一定关系的, 61 //firstContent 和 secondContent 的可移动距离之和必须等于 parent的宽度 62 firstLeft = CGPointMake(self.frame.size.width/2 - kDistance, self.frame.size.height/2); 63 firstRight = self.center; 64 65 secondLeft = self.center; 66 secondRight = CGPointMake(self.frame.size.width+secondContent.view.frame.size.width/2-kDistance, self.frame.size.height/2); 67 68 firstContent.view.center = firstRight; 69 secondContent.view.center = secondRight; 70 status = DrawerStatusRight; 71 72 // 加入手势 73 UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(handleTap:)]; 74 tap.numberOfTapsRequired = 1; 75 tap.enabled = YES; 76 [secondContent.view addGestureRecognizer:tap]; 77 78 UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(handlePan:)]; 79 pan.enabled = YES; 80 [secondContent.view addGestureRecognizer:pan]; 81 82 //设置第一个view 的起始center 83 firstContentCenter = firstContent.view.center; 84 85 //这个是关键,为什么要这样算,为了防止两个content view之间的间距发生改变, 86 //所以firstContent 和 secondContent 的可移动距离之和必须等于 parent的宽度 87 moveScale = (float)kDistance/(float)(self.frame.size.width - kDistance); 88 } 89 90 return self; 91 } 92 93 94 -(void)handleTap:(UITapGestureRecognizer *)tap{ 95 // 当secondController完全出现在屏幕中时,则只有点击左上角时才有用 96 // 呵呵,没啥好写的,就是简单地控制下点击范围 97 if (status == DrawerStatusLeft) { 98 99 CGPoint p = [tap locationInView:secondContent.view]; 100 if (p.x > kDistance || p.y > 50) { 101 return; 102 } 103 } 104 105 [UIView animateWithDuration:0.3 delay:0.01 options:UIViewAnimationOptionCurveLinear animations:^{ 106 if (status == DrawerStatusRight) { 107 secondContent.view.center = secondLeft; 108 109 firstContent.view.center = firstLeft; 110 status = DrawerStatusLeft; 111 }else{ 112 secondContent.view.center = secondRight; 113 firstContent.view.center = firstRight; 114 status = DrawerStatusRight; 115 } 116 } completion:nil]; 117 118 } 119 120 121 -(void)handlePan:(UIPanGestureRecognizer *)pan{ 122 123 CGPoint point = [pan translationInView:self]; 124 125 if (secondContent.view.center.x + point.x < secondLeft.x) { 126 127 secondContent.view.center = secondLeft; 128 firstContent.view.center = firstLeft; 129 130 }else if (secondContent.view.center.x + point.x > secondRight.x){ 131 132 secondContent.view.center = secondRight; 133 134 firstContent.view.center = firstRight; 135 136 }else{ 137 secondContent.view.center = CGPointMake(secondContent.view.center.x + point.x, secondContent.view.center.y); 138 //firstContent的移动距离必须按照比例计算 139 firstContent.view.center = CGPointMake(firstContent.view.center.x + point.x*moveScale, firstContent.view.center.y); 140 } 141 142 [pan setTranslation:CGPointMake(0, 0) inView:self]; 143 if (pan.state == UIGestureRecognizerStateEnded) { 144 [UIView animateWithDuration:0.3 delay:0.01 options:UIViewAnimationOptionCurveLinear animations:^{ 145 if (secondContent.view.center.x < secondRight.x*4/5) { 146 147 secondContent.view.center = secondLeft; 148 149 firstContent.view.center = firstLeft; 150 status = DrawerStatusLeft; 151 }else{ 152 153 secondContent.view.center = secondRight; 154 firstContent.view.center = firstRight; 155 156 status = DrawerStatusRight; 157 } 158 } completion:nil]; 159 } 160 } 161 162 @end
上面两段是主要的代码了,下面是使用的地方
1 // 2 // ViewController.m 3 // SlideDrawer 4 // 5 // Created by PSH_Chen_Tao on 10/12/13. 6 // Copyright (c) 2013 wolfman. All rights reserved. 7 // 8 9 #import "ViewController.h" 10 11 #import "FirstViewController.h" 12 #import "SecondViewController.h" 13 #import "Drawer.h" 14 @interface ViewController () 15 16 @end 17 18 @implementation ViewController 19 20 - (void)viewDidLoad 21 { 22 [super viewDidLoad]; 23 // Do any additional setup after loading the view, typically from a nib. 24 25 FirstViewController *fisrt = [[FirstViewController alloc]initWithNibName:@"FirstViewController" bundle:nil]; 26 27 SecondViewController *second = [[SecondViewController alloc]initWithNibName:@"SecondViewController" bundle:nil]; 28 29 Drawer *drawer = [[Drawer alloc]initWithParent:self firstContent:fisrt secondContent:second]; 30 [self.view addSubview:drawer]; 31 } 32 33 - (void)didReceiveMemoryWarning 34 { 35 [super didReceiveMemoryWarning]; 36 // Dispose of any resources that can be recreated. 37 } 38 39 @end
呵呵,可以看看效果,是不是感觉好点。。