如今很多App應用,都用到了側邊欄的效果,比如網易新聞(還帶有偏移縮小),今日頭條(普遍這種),Path(最先應用這種抽屜效果,所以這種效果也叫Path效果),code4App上已經有很多網友寫的第三方側邊欄類,大家可以直接拿來用.這裏我主要的是介紹一下這種效果的實現原理,涉及了幾個知識點,在其他地方也能用到.
UINavigationController和UITabBarController是2個主要的視圖控制容器,都有屬性viewControllers,能夠很好地管理多個視圖控制器.但有的時候,系統給的有很大的侷限性,我們做效果,更多是基於系統UI,自定義很多的控件.就拿側邊欄效果舉例,表面上看上去,它只有3個UIViewController,left-mid-right,中間的minViewController作爲根控制器.其實,不是的,有4個,應該還有一個RootViewController,作爲管理它們的視圖控制容器,它的作用,就像UITabBarController,只做管理那3個視圖控制器之用,並不參與任何子ViewController的視圖,數據的操作.
這裏,又要講一下UIView和UIViewController的關係了.UIView(視圖)在展示用戶界面和響應用戶界面交互方面起很重要的作用,我們所看到的內容,都是通過視圖展示給我們的,屬於MVC中的V.而UIViewController(視圖控制器),保存所管理視圖的引用,協調Model和View之間的數據,通常作爲委託或者數據源,簡而言之就是實現數據操縱的地方.爲什麼要講這個呢?因爲我有朋友,直接在一個RootViewController加了3個UIView,我就說他,你幹嘛不用UIViewController,他說你那不是控制器嘛,又不是視圖.....暈倒,每個UIViewController都有自己管理的view,直接.view不就出來了嘛.
不僅僅是側邊欄是這樣,網易App主界面標籤控制的內容也是這樣,標籤"頭條"-"娛樂"-"體育"-"財經"-"科技"等等,其實每個都是對應了一個UIViewController,而不是UITableView,MVC的本意就是M和V不交互,數據的操作還是要放在controller中的,利用iOS5新出的屬性addChildViewController,這樣就不需要在一個controller處理所有的標籤內容,而是將不同數據的處理各自對應一個viewController,一個主UIViewController用來做控制作用(額,是不是有點混亂,沒關係,我在下一章會將網易標籤欄對應各個內容的功能剖析出來)
@展示主要代碼:
- - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
- {
- self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
- // Override point for customization after application launch.
- self.window.backgroundColor = [UIColor whiteColor];
- DNWLeftViewController * leftVC = [[DNWLeftViewController alloc] init];
- //UINavigationController * leftNC = [[UINavigationController alloc] initWithRootViewController:leftVC];
- DNWRightViewController * rightVC = [[DNWRightViewController alloc] init];
- //UINavigationController * rightNC = [[UINavigationController alloc] initWithRootViewController:rightVC];
- DNWMidViewController * midVC = [[DNWMidViewController alloc] init];
- UINavigationController * midNC = [[UINavigationController alloc] initWithRootViewController:midVC];
- DNWRootViewController * rootVC = [[DNWRootViewController alloc] init];
- //UINavigationController * rootNC = [[UINavigationController alloc] initWithRootViewController:rootVC];
- rootVC.leftViewController = leftVC;
- rootVC.rightViewController = rightVC;
- rootVC.midViewController = midNC;
- self.window.rootViewController = rootVC;
- [self.window makeKeyAndVisible];
- return YES;
- }
- - (void)viewDidLoad
- {
- [super viewDidLoad];
- // Do any additional setup after loading the view.
- /**
- * 1.加載視圖的順序,中間視圖放在最後加,因爲程序一開始它要顯示在最上面
- * 2.所有ViewController的View如果不設置的話,默認全屏大小(標籤欄展示效果的話,所有的ViewController都是標籤欄以下大小)
- * 3.這裏的self-->RootViewController,不要設置爲導航控制器
- * 4.只做視圖切換,不做其他任何數據操作
- * 5.手勢切換,原理一樣,自己可以加上,點擊或者拖拉都想,這個我就不在這裏描述了
- *
- */
- [self addChildViewController:self.leftViewController];
- [self.view addSubview:self.leftViewController.view];
- [self addChildViewController:self.rightViewController];
- [self.view addSubview:self.rightViewController.view];
- [self addChildViewController:self.midViewController];
- [self.view addSubview:_midViewController.view];
- UIButton *leftButton = [UIButton buttonWithType:UIButtonTypeSystem];
- leftButton.frame = CGRectMake(0, 20, 40, 40);
- [leftButton setTitle:@"left" forState:UIControlStateNormal];
- [leftButton addTarget:self action:@selector(didClickLeftBarButtonAction:) forControlEvents:UIControlEventTouchUpInside];
- [self.midViewController.view addSubview:leftButton];
- UIButton *rightButton = [UIButton buttonWithType:UIButtonTypeSystem];
- rightButton.frame = CGRectMake(280 ,20, 40, 40);
- [rightButton setTitle:@"right" forState:UIControlStateNormal];
- [rightButton addTarget:self action:@selector(didClickRightBarButtonAction:) forControlEvents:UIControlEventTouchUpInside];
- [self.midViewController.view addSubview:rightButton];
- }
- // 網易側邊欄效果
- - (void)didClickLeftBarButtonAction:(UIBarButtonItem *)leftButton{
- // 用這個判斷條件是爲了左邊視圖出來後,再點擊按鈕能夠回去
- if (self.midViewController.view.frame.origin.x == 0) {
- [UIView animateWithDuration:0.3 animations:^{
- // ScreenWidth ScreenHeight 屏幕實際大小宏
- self.leftViewController.view.frame = CGRectMake(0, 0, ScreenWidth, ScreenHeight);
- // 也可以通過這種方式來實現
- //self.midViewController.view.transform = CGAffineTransformTranslate(self.midViewController.view.transform, 280,64 );
- self.midViewController.view.frame = CGRectMake(280, 64, ScreenWidth, ScreenHeight-64*2);
- self.rightViewController.view.frame = CGRectMake(280, 64, ScreenWidth, ScreenHeight-64*2);
- } completion:^(BOOL finished) {
- }];
- }else{
- [UIView animateWithDuration:0.3 animations:^{
- self.midViewController.view.frame = CGRectMake(0, 0, ScreenWidth, ScreenHeight);
- self.rightViewController.view.frame = CGRectMake(0, 0, ScreenWidth, ScreenHeight);
- } completion:^(BOOL finished) {
- }];
- }
- }
- // 標準側邊欄效果
- - (void)didClickRightBarButtonAction:(UIBarButtonItem *)rightButton{
- if (_midViewController.view.frame.origin.x == 0) {
- [UIView animateWithDuration:1.1 animations:^{
- _midViewController.view.frame = CGRectMake(-280, 0, ScreenWidth, ScreenHeight);
- _rightViewController.view.frame = CGRectMake(0, 0, ScreenWidth, ScreenHeight);
- } completion:^(BOOL finished) {
- }];
- }else{
- [UIView animateWithDuration:1.1 animations:^{
- _midViewController.view.frame = CGRectMake(0, 0, ScreenWidth, ScreenHeight);
- _rightViewController.view.frame = CGRectMake(0, 0, ScreenWidth, ScreenHeight);
- } completion:^(BOOL finished) {
- }];
- }
- }