容器视图控制器的创建(WORKING WITH CUSTOM CONTAINER VIEW CONTROLLERS)
来源:互联网 发布:淘宝上手机解锁可靠吗 编辑:程序博客网 时间:2024/05/21 14:43
原文:http://www.thinkandbuild.it/working-with-custom-container-view-controllers/
我们将创建一个点击按钮弹出controller(点击按钮和弹出的次数没有限制)的应用。
下面简要说明如何实现
Container: 它继承自UIViewController,有一个subview属性,subview属性是其他子控制器和点击按钮后生成的新Detail Controller 共同的容器。
Detail: 它是一个简单的UIViewController,它包括一个标签和一个UIGestureRecognizer。在它的视图上滑动,标签的颜色会随机变化。此类的实例将成为容器视图控制器的子控制器。它的视图会赋值给容器的detailView,但是仍有自身管理,并接受手势事件。
源码:https://github.com/ariok/TB_ControllerContainment
添加子控制器
在正式开始之前,感谢FlatUI Kit (https://github.com/Grouper/FlatUIKit) 的作者Jack Flintermann.。FlatUI Kit 真是个特别炫酷的类库。
打开 ContainerViewController.m 找到presentDetailController 函数。这个函数完成新Detail controller加入容器视图控制器的操作。下面我们来看仔细代码
- (void)presentDetailController:(UIViewController*)detailVC{ //0. Remove the current Detail View Controller showed if(self.currentDetailViewController){ [self removeCurrentDetailViewController]; } //1. Add the detail controller as child of the container [self addChildViewController:detailVC]; //2. Define the detail controller's view size detailVC.view.frame = [self frameForDetailController]; //3. Add the Detail controller's view to the Container's detail view and save a reference to the detail View Controller [self.detailView addSubview:detailVC.view]; self.currentDetailViewController = detailVC; //4. Complete the add flow calling the function didMoveToParentViewController [detailVC didMoveToParentViewController:self]; }
Step 0
此步骤我们一会儿再讨论,但这步的本质就是将当前正在显示的Detail ViewController 从容器中删除。
Step 1
IOS为了自定义容器控制器,加入了很多新的函数。addChildViewController 就是其中一个。就这么简单,我们在容器控制器中加了一个Detail Controller。
Step 2
新创建的Detail Controller的视图将要与容器控制器中预定义好的视图进行连接,所以我们要修改预定义视图的frame。
Step 3
现在,我们将Detail Controller的视图添加到容器的detailView上,并将新建的Detail Controller作为当前的Detail Controller。
Step 4
didMoveToParentViewController也是新加入UIViewController类的一个函数。调用这个函数后,我们发送给Detail Controller 实例一个消息,告诉它,它现在是其他控制器的子控制器。删除子控制器
现在,我们来看 removeCurrentDetailViewController (与上面函数在同一.m文件中)
Step 1
我们通过在willMoveToParentViewController 以nil 为参数,给current Detail Controller 发送一条信息,通知它将要从父控制器中移除。
Step 2
将current Detail controller的视图从父视图中移除。
Step 3
通过调用标准函数removeFromParentViewController,我们将current Detail Controlle从容器中移除。当这个函数被调用的时候,Detail Controller会自动调用 didMoveToParentViewController,调用时的参数为nil。
结果
第一个Detail Controller在容器的viewDidLoad函数中被创建。initWithString:withColor函数帮我们创建一个DetailViewController实例。我们调用presentDetailController 函数,将刚刚创建的实例作为当前的Detail Controller (current Detail Controller)。就像之前提到的,按钮在容器控制器的主视图上,当我们按下后,就展示一个新的Detail Controller。我们通过addDetailController来添加按钮事件,代码不多,如下:
- (IBAction)addDetailController:(id)sender { DetailViewController *detailVC = [[DetailViewController alloc]initWithString:@"This is a new viewController!" withColor:[UIColor asbestosColor]]; /* Mode 1 */ [self presentDetailController:detailVC]; /* Mode 2 */ //[self swapCurrentControllerWith:detailVC];}
添加动画效果
还没有提到动画,下面说说。当我们push一个视图控制器的时候可以加入不同的动画,是个很好的想法。我们不去分别创建方法来添加或删除Detail Controllers,而是将所有操作都放在一个名为swapCurrentControllerWith的函数,我们将新建的ViewController做为参数传入,下面是完整代码:
- (void)swapCurrentControllerWith:(UIViewController*)viewController{ //1. The current controller is going to be removed [self.currentDetailViewController willMoveToParentViewController:nil]; //2. The new controller is a new child of the container [self addChildViewController:viewController]; //3. Setup the new controller's frame depending on the animation you want to obtain viewController.view.frame = CGRectMake(0, 2000, viewController.view.frame.size.width, viewController.view.frame.size.height); //The transition automatically removes the old view from the superview and attaches the new controller's view as child of the //container controller's view //Save the button position... we'll need it later CGPoint buttonCenter = self.button.center; [self transitionFromViewController:self.currentDetailViewController toViewController:viewController duration:1.3 options:0 animations:^{ //The new controller's view is going to take the position of the current controller's view viewController.view.frame = self.currentDetailViewController.view.frame; //The current controller's view will be moved outside the window self.currentDetailViewController.view.frame = CGRectMake(0, -2000, self.currentDetailViewController.view.frame.size.width, self.currentDetailViewController.view.frame.size.width); self.button.center = CGPointMake(buttonCenter.x,1000); } completion:^(BOOL finished) { //Remove the old view controller [self.currentDetailViewController removeFromParentViewController]; //Set the new view controller as current self.currentDetailViewController = viewController; [self.currentDetailViewController didMoveToParentViewController:self]; //reset the button position [UIView animateWithDuration:0.5 animations:^{ self.button.center = buttonCenter; }]; }];}
结论
如果你想添加一个新的子控制器并且删除之前的,按照以下步骤来做,这是每种导航模式里(navigation patterns 比如Navigation 、TabBar)共同的。
1 Current detail controller: [current willMoveToParentViewController:nil] //当前的控制器
2 Next detail controller: [container addChildViewController:next] //下一个控制器
2.B Next detail controller: [next willMoveToParentViewController:self] (自动调用2)
3 Next detail controller: [container.view addSubview:next.view]
4 Current detail controller: [current.view removeFromSuperView]
5 Current detail controller: [current removeFromParentViewController]
6 Current detail controller: [current didMoveToParentViewController:nil] (自动被5调用)
7 Next detail controller: [next didMoveToParentViewController:self]
你可以利用这些新加入的函数来创建自己的导航模式。显然,UINavigationController 和 UITabBarController 就是很好的例子。
他们有不同的逻辑和不同的用处,但是他们有共同的地方,那就是每次只为用户展示一个View Controller。
另外一个关于容器控制器的例子是UISplitViewController,它可以一次展示给用户两个控制器。
简单说,你的自定义容器的本质任务就是管理controller,规定哪个需要显示,哪个不需要,如何让用户在controller之间进行切换。
- 容器视图控制器的创建(WORKING WITH CUSTOM CONTAINER VIEW CONTROLLERS)
- WORKING WITH CUSTOM CONTAINER VIEW CONTROLLERS
- Custom Container View Controller(自定义容器视图控制器)
- [链接]Creating Custom Container View Controllers
- 有关custom container of view controllers
- Container View(sb-容器视图)
- Custom Container View Controller容器vc
- 视图控制器中的资源管理 Resource Management in View Controllers [苹果官方文档的翻译]
- 视图控制器的view创建方式
- 使用视图控制器容器(翻译自苹果官方文档 Implementing a Container View Controller)
- iOS 容器控制器 (Container View Controller)
- Creating Custom Content View Controllers
- Container View 是用来在一个视图控制器上添加子试图控制器的
- 关于自定义视图容器(Container View Controller)
- 关于自定义视图容器(Container View Controller)
- Custom Container View Controller
- Custom Container View Controller
- Custom Container View Controller
- Spiral Matrix & Spiral Matrix II & Rotate Image
- Android工程目录
- poll机制分析
- 表单中PHP的错误提示:Notice: Undefined index: submit in D:\wamp\www\bbs\add.php on line 4
- ios开发之实现长按UITableViewCell弹出UIMenuController
- 容器视图控制器的创建(WORKING WITH CUSTOM CONTAINER VIEW CONTROLLERS)
- 载入jQuery库的最佳方法
- VMware10 无法联网的一种解决办法
- 《你必须知道的495个C语言问题》笔记--库函数
- 空间分析:区域分析之基于shapfile的栅格数据统计
- 支持向量机(四)-- 核函数
- 黑马程序员笔记——Java流程控制
- redhat上安装oracle11g
- ios tableview 那些事(二十) ios7 分割线短 15 像素