为了简化描述,下面统一使用VC来代替ViewController。
我想实现的效果——网页风格的tab选项卡:
我的思路:在RootVC中定义两个button,并额外定义两个对应的VC,点击button时将对应的VC添加RootVC(addSubView:
)的指定区域。不知道这样做可行不?
如果思路是对的,我想继续优化成可使用手势滑动来切换选项卡,不知道上面的思路方案在手势识别上有啥问题不?
谢谢大家
1
black 2015-05-21 18:41:11 +08:00 1
可行,需要注意的是视图转换不要单纯的 addSubView: or removeFromSuperview,而是应该将 RootViewController 做成 Container View Controller。另外 tab 多的话,还需要注意内存管理。
建议读一遍文档后再动手实现 https://developer.apple.com/library/ios/featuredarticles/ViewControllerPGforiPhoneOS/CreatingCustomContainerViewControllers/CreatingCustomContainerViewControllers.html |
2
lionyue 2015-05-22 10:57:20 +08:00 1
最好用childviewcontroller来做。两个page各对应一个view controller,都作为当前view controller的childviewcontroller,view controller的切换使用transitionFromViewController:toViewController:
|
3
pysama OP 非常感谢black和lionyue的方案。
我晚上再动手试试。 |
4
pysama OP |
5
pysama OP 突然想到思路,tableView的didSelectedRow 方法+ navigation的pushVc方法结合。等候回去试试
|
7
ryrubyy 2015-05-23 15:31:22 +08:00 via Android 1
这让我想到了框架。如果网页的宽度过大,手势切换会不会有一些困难?参考图片放大后的手势切换。
另外,v2创建新讨论串: [http://v2ex.com/new/]加节点ID |
8
pysama OP @black @lionyue @ryrubyy tableCell点击事件很快搞定了。但利用container实现简单tab我至今没搞定看了文档和相关文章还是搞不定。只好厚着脸皮再次求助大家了。我的做法如下:
新建一个项目,往SB中拖入两个button和一个containerView(当我拖入一个containerView的时候,会自动生成一个与之关联的viewController,这个应该就是containerViewController了吧)。然后,我又往SB中拖入了两个VC(分别用于显示两个button的对应内容页面)。 然后在主VC的viewDidLoad方法中开始写代码: containerVC = [根据storyboardId获取 ]; firstDetailVC = [根据storyboardId获取 ]; secondDetailVC = [根据storyboardId获取 ]; //添加childVC [containerVC addChildViewController: firstDetailVC] ; [containerVC addChildViewController: secondDetailVC] ; 处理按钮点击如下: [containerVC transitionFromViewController:firstDetailVC toViewController:secondDetailVC duration:0.5 options:0 animations:nil completion:nil]; 代码完了。运行时,container区域没有默认的firstDetailVC的内容(我前面已经addChildVC了啊,甚至我尝试[containerVC.vied addSubView: firstDetailVC.view也没有任何作用),点击按钮也没有反映,也没有报错。 求指导。谢谢大家! |
9
black 2015-05-23 20:43:48 +08:00 1
你先用你自己的思路实现最基本的视图切换:
"在RootVC中定义两个button,并额外定义两个对应的VC,点击button时将对应的VC添加RootVC(addSubView:)的指定区域。" 然后再读一遍文档,并把你的实现按文档重写一遍。 再从头思考你当初是什么地方没有理解,导致实现不了想要的效果。 这是一个不断学习和反思的过程。 |
10
pysama OP @black 恩,好的。用最开始的思路实现很直观,简单调整下即可。
在主VC中拖入一个View,并将该view绑定到一个属性“wrapView”,然后在viewDidLoad中,默认将第一个页面的内容添加到该view中: [self.wrapView addSubview:firstVC.view]; 然后给两个按钮的touch up inslide 事件中按需加入对应的view,如下: //clear view [firstVC.view removeFromSuperview]; [secondVC.view removeFromSuperview]; //show corresponding view [self.wrapView addSubview:secondVC.view]; 我再去读一边文档理解下。谢谢black的建议 |
11
pysama OP 我现在把功能最简化,只需要container能够显示childVC的内容就够了。可是我用下面的代码还是不行:
[self addChildViewController:content]; // 1 content.view.frame = [self frameForContentController]; // 2 [self.view addSubview:self.currentClientView]; 突然之间,我尝试把addChild的代码放在containerVC的viewDidLoad中,前端就成正常显示了。 而我之前都是在RootVC的viewDidLoad中去写addChild的代码导致没正常显示。(即使我在containerVC中将addChild的操作做为public方法,然后在RootVC中去调用这个方法也是不行)。 那么问题又来了,如何在containerVC外部**正确地**去执行containerVC里面定义的相关方法呢(比如addChild,transitioinVC等) |
12
lionyue 2015-05-24 13:47:21 +08:00
```Objective-c
- (void)viewDidLoad { [super viewDidLoad]; UIButton *button1 = [[UIButton alloc] initWithFrame:CGRectMake(10, 10, 50, 40)]; [button1 setBackgroundColor:[UIColor blackColor]]; [button1 setTitle:@"tab1" forState:UIControlStateNormal]; [button1 addTarget:self action:@selector(button1Taped:) forControlEvents:UIControlEventTouchUpInside]; [self.view addSubview:button1]; UIButton *button2 = [[UIButton alloc] initWithFrame:CGRectMake(70, 10, 50, 40)]; [button2 setBackgroundColor:[UIColor blackColor]]; [button2 setTitle:@"tab2" forState:UIControlStateNormal]; [button2 addTarget:self action:@selector(button2Taped:) forControlEvents:UIControlEventTouchUpInside]; [self.view addSubview:button2]; vc1 = [ViewController1 new]; vc1.view.frame = CGRectMake(0, 80, 320, 400); vc1.view.backgroundColor = [UIColor greenColor]; vc2 = [ViewController2 new]; vc2.view.frame = CGRectMake(0, 80, 320, 400); vc2.view.backgroundColor = [UIColor orangeColor]; [self addChildViewController:vc1]; [self addChildViewController:vc2]; [self.view addSubview:vc1.view]; } - (void)button1Taped:(id)sender { [self transitionFromViewController:vc2 toViewController:vc1 duration:1 options:UIViewAnimationOptionCurveEaseInOut animations:NULL completion:NULL]; } - (void)button2Taped:(id)sender { [self transitionFromViewController:vc1 toViewController:vc2 duration:1 options:UIViewAnimationOptionCurveEaseInOut animations:NULL completion:NULL]; } ``` |
13
pysama OP |
14
eeeeeeve 2015-05-24 16:05:21 +08:00
手机滑动如何实现呢?
|
15
black 2015-05-24 18:48:23 +08:00 1
@pysama
Container View Controller 是一个 iOS 5 开始引入的概念,一个 view controller A 通过 addChildViewController 添加另一个 view controller B,这样它们之间就形成了 Parent/Child 的 view controller 层次关系,在这层关系里,A 就是所谓的 container view controller。此时 A 可以通过 self.childViewControllers 属性访问到所有的 children(B 就包含在里面),B 也能够通过 self.parentViewController 访问到 A。 像 UIKit 里面最常用的 UINavigationController, UITabBarController 都是 container view controller。 再比如我的开源组件,支持手势前进和后退的 CWStackController,也是一个 container view controller, https://github.com/guojiubo/CWStackController。类似这样的例子 GitHub 上数不胜数。 至于为什么我们现在都要采用这套机制来管理视图之间的关系,最重要的是为了 view controller 生命周期的各个事件,包括旋转事件,能有效的传递下去: "Once you add a child to a container, the container automatically forwards rotation and appearance callbacks to the child view controllers as soon as an event occurs that requires the message to be forwarded." lionyue 的代码示例里面也并不是像你说的没有用到 container view controller。 |
16
pysama OP @black 感谢black的耐心解答
我也反思了这几天自己的一些错误理解: 1. 我以为要从xcode右下角拖入的containerView才能成为container,其实不然,一个普通的VC也是可以当作container,比如上面@lionyue 的demo中的RootVC就是一个container; 2. 我之前是把button放在container的外部的,这样是没办法操作container里面的展示或切换的(至少我目前没找到方式去操作)。其实只要把button也放入到同一个container,在container内部就能很方便的完成 childVC的展示和切换(@lionyue的demo就是这样) 稍后再去体验下black的CWStackController,感谢分享~ |