V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
iOS 开发实用技术导航
NSHipster 中文版
http://nshipster.cn/
cocos2d 开源 2D 游戏引擎
http://www.cocos2d-iphone.org/
CocoaPods
http://cocoapods.org/
Google Analytics for Mobile 统计解决方案
http://code.google.com/mobile/analytics/
WWDC
https://developer.apple.com/wwdc/
Design Guides and Resources
https://developer.apple.com/design/
Transcripts of WWDC sessions
http://asciiwwdc.com
Cocoa with Love
http://cocoawithlove.com/
Cocoa Dev Central
http://cocoadevcentral.com/
NSHipster
http://nshipster.com/
Style Guides
Google Objective-C Style Guide
NYTimes Objective-C Style Guide
Useful Tools and Services
Charles Web Debugging Proxy
Smore
pysama
V2EX  ›  iDev

请教实现网页风格的 tab 选项卡的思路

  •  
  •   pysama · 2015-05-21 16:46:41 +08:00 · 3533 次点击
    这是一个创建于 3481 天前的主题,其中的信息可能已经有所发展或是发生改变。

    为了简化描述,下面统一使用VC来代替ViewController。

    我想实现的效果——网页风格的tab选项卡:

    browserTab

    我的思路:在RootVC中定义两个button,并额外定义两个对应的VC,点击button时将对应的VC添加RootVC(addSubView:)的指定区域。不知道这样做可行不?

    如果思路是对的,我想继续优化成可使用手势滑动来切换选项卡,不知道上面的思路方案在手势识别上有啥问题不?

    谢谢大家

    16 条回复    2015-05-25 09:31:37 +08:00
    black
        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
    lionyue
        2
    lionyue  
       2015-05-22 10:57:20 +08:00   ❤️ 1
    最好用childviewcontroller来做。两个page各对应一个view controller,都作为当前view controller的childviewcontroller,view controller的切换使用transitionFromViewController:toViewController:
    pysama
        3
    pysama  
    OP
       2015-05-22 13:42:10 +08:00
    非常感谢black和lionyue的方案。
    我晚上再动手试试。
    pysama
        4
    pysama  
    OP
       2015-05-23 13:39:22 +08:00 via iPhone
    手机端上v2ex没找到发布问题的入口。我只能在这里回帖召唤大神了。

    我在tableView中引入了一个自定义的tableCell(xib格式)。现在我想给cell和detail页面之间加一个segue来实现页面跳转。我实在不知道如何下手了。

    用默认的cell时,我可以直接按住右键将cell和detail页面用segue连接起来。但自定义的cell是一个xib文件。不在sb里面。如何操作呢?

    @lionyue @black 求指导
    ps:边等公交边打字,格式可能不太美观,见谅了
    pysama
        5
    pysama  
    OP
       2015-05-23 13:58:08 +08:00 via iPhone
    突然想到思路,tableView的didSelectedRow 方法+ navigation的pushVc方法结合。等候回去试试
    black
        6
    black  
       2015-05-23 14:12:35 +08:00
    @pysama 思路是对的~
    ryrubyy
        7
    ryrubyy  
       2015-05-23 15:31:22 +08:00 via Android   ❤️ 1
    这让我想到了框架。如果网页的宽度过大,手势切换会不会有一些困难?参考图片放大后的手势切换。
    另外,v2创建新讨论串: [http://v2ex.com/new/]加节点ID
    pysama
        8
    pysama  
    OP
       2015-05-23 19:53:55 +08:00
    @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也没有任何作用),点击按钮也没有反映,也没有报错。

    求指导。谢谢大家!
    black
        9
    black  
       2015-05-23 20:43:48 +08:00   ❤️ 1
    你先用你自己的思路实现最基本的视图切换:

    "在RootVC中定义两个button,并额外定义两个对应的VC,点击button时将对应的VC添加RootVC(addSubView:)的指定区域。"

    然后再读一遍文档,并把你的实现按文档重写一遍。

    再从头思考你当初是什么地方没有理解,导致实现不了想要的效果。

    这是一个不断学习和反思的过程。
    pysama
        10
    pysama  
    OP
       2015-05-23 21:47:48 +08:00
    @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的建议
    pysama
        11
    pysama  
    OP
       2015-05-24 12:40:06 +08:00
    我现在把功能最简化,只需要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等)
    lionyue
        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];

    }

    ```
    pysama
        13
    pysama  
    OP
       2015-05-24 14:19:19 +08:00
    @lionyue 感谢你的回复,

    你的demo中貌似没用到containerVC呢。

    要不是学习这个containerVC,我用addSubView也可以放方便的实现。
    eeeeeeve
        14
    eeeeeeve  
       2015-05-24 16:05:21 +08:00
    手机滑动如何实现呢?
    black
        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。
    pysama
        16
    pysama  
    OP
       2015-05-25 09:31:37 +08:00
    @black 感谢black的耐心解答

    我也反思了这几天自己的一些错误理解:

    1. 我以为要从xcode右下角拖入的containerView才能成为container,其实不然,一个普通的VC也是可以当作container,比如上面@lionyue 的demo中的RootVC就是一个container;

    2. 我之前是把button放在container的外部的,这样是没办法操作container里面的展示或切换的(至少我目前没找到方式去操作)。其实只要把button也放入到同一个container,在container内部就能很方便的完成 childVC的展示和切换(@lionyue的demo就是这样)

    稍后再去体验下black的CWStackController,感谢分享~
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2585 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 04:18 · PVG 12:18 · LAX 20:18 · JFK 23:18
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.