我正在尝试制作一个跨越三个标签的表单。您可以在下面的屏幕截图中看到标签的位置。当用户点击选项卡时,容器视图应该更新并显示我拥有的特定视图控制器。
选项卡1 =查看控制器1
标签2 =查看控制器2
选项卡3 =查看控制器3
上面显示的视图控制器具有PPAddEntryViewController.m类。我在这个类中为Container视图创建了一个插座,现在有一个Container View属性:
@property (weak, nonatomic) IBOutlet UIView *container;
我的IBActions也准备好了我的标签:
- (IBAction)tab1:(id)sender {
//...
}
- (IBAction)tab2:(id)sender {
//...
}
- (IBAction)tab3:(id)sender {
//...
}
如何在这些IBActions中设置容器以更改容器视图所包含的视图控制器?
在其他一些事情中,这是我尝试过的事情:
UIViewController *viewController1 = [self.storyboard instantiateViewControllerWithIdentifier:@"vc1"];
_container.view = viewController1;
......但它不起作用。提前谢谢。
答案 0 :(得分:16)
您希望将容器视图添加到视图中,以及何时切换'子视图控制器按下相应的segue并执行正确的设置工作。
在Storyboard中,您只能将一个Embed Segue连接到Container View。所以你创建了一个中间处理控制器。 make embed segue并为其指定一个标识符,例如EmbededSegueIdentifier。
在父视图中,控制器连接按钮或任何您想要的内容,并在prepare segue中引用您的子视图控制器。一旦父视图控制器加载segue就会被触发。
@property (weak, nonatomic) MyContainerViewController *myContainerViewController;
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:@"EmbeddedSegueIdentifier"]) {
self.myContainerViewController = segue.destinationViewController;
}
}
按下按钮应该很容易委托给容器控制器。
下一部分代码部分借用了几个来源,但关键的变化是使用自动布局而不是显式帧。没有什么可以阻止您简单地更改[self addConstraintsForViewController:]
的行viewController.view.frame = self.view.bounds
。在故事板中,此容器视图控制器不会执行任何与目标子视图控制器相关的操作。
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(@"%s", __PRETTY_FUNCTION__);
[self performSegueWithIdentifier:@"FirstViewControllerSegue" sender:nil];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
UIViewController *destinationViewController = segue.destinationViewController;
if ([self.childViewControllers count] > 0) {
UIViewController *fromViewController = [self.childViewControllers firstObject];
[self swapFromViewController:fromViewController toViewController:destinationViewController];
} else {
[self initializeChildViewController:destinationViewController];
}
}
- (void)initializeChildViewController:(UIViewController *)viewController
{
[self addChildViewController:viewController];
[self.view addSubview:viewController.view];
[self addConstraintsForViewController:viewController];
[viewController didMoveToParentViewController:self];
}
- (void)swapFromViewController:(UIViewController *)fromViewController toViewController:(UIViewController *)toViewController
{
[fromViewController willMoveToParentViewController:nil];
[self addChildViewController:toViewController];
[self transitionFromViewController:fromViewController toViewController:toViewController duration:0.2f options:UIViewAnimationOptionTransitionCrossDissolve animations:nil completion:^(BOOL finished) {
[self addConstraintsForViewController:toViewController];
[fromViewController removeFromParentViewController];
[toViewController didMoveToParentViewController:self];
}];
}
- (void)addConstraintsForViewController:(UIViewController *)viewController
{
UIView *containerView = self.view;
UIView *childView = viewController.view;
[childView setTranslatesAutoresizingMaskIntoConstraints:NO];
[containerView addSubview:childView];
NSDictionary *views = NSDictionaryOfVariableBindings(childView);
[containerView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[childView]|"
options:0
metrics:nil
views:views]];
[containerView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[childView]|"
options:0
metrics:nil
views:views]];
}
#pragma mark - Setters
- (void)setSelectedControl:(ViewControllerSelectionType)selectedControl
{
_selectedControl = selectedControl;
switch (self.selectedControl) {
case kFirstViewController:
[self performSegueWithIdentifier:@"FirstViewControllerSegue" sender:nil];
break;
case kSecondViewController:
[self performSegueWithIdentifier:@"SecondViewControllerSegue" sender:nil];
break;
default:
break;
}
}
您需要的最后一件事是自定义segue,它不会执行任何操作,使用从Container View Controller调用的相应segue标识符到达每个目标。如果你没有放入空的执行方法,应用程序将崩溃。通常你可以在这里做一些自定义过渡动画。
@implementation SHCDummySegue
@interface SHCDummySegue : UIStoryboardSegue
@end
- (void)perform
{
// This space intentionally left blank
}
@end
答案 1 :(得分:11)
我最近找到了完美示例代码,用于我尝试做的事情。它包括Storyboard实现和所有相关的segue和代码。这真的很有帮助。
答案 2 :(得分:7)
更新:正如您之前发现的那样,推荐使用UITabBarController。如果您想要自定义高度,这是一个良好的开端:My way of customizing UITabBarController's tabbar - Stackoverflow answer
从iOS 5+开始,您可以通过此API自定义外观; UIAppearance Protocol Reference。这是一个很好的教程:How To Customize Tab Bar Background and Appearance
实现您正在寻找的最明显的方法是简单地管理3个不同的容器(它们是简单的UIViews)并实现它们中的每一个以容纳每个选项卡所需的任何内容视图(使用隐藏属性容器)。
以下是使用不同容器可以实现的示例:
这些容器“交换”当然可以动画。关于你的自我回答,你可能选择了正确的方法来做到这一点。
答案 3 :(得分:2)
有一个成员变量来保存viewController:
UIViewController *selectedViewController;
现在在IBActions中,切换那个AND视图。 e.g。
- (IBAction)tab1:(id)sender {
UIViewController *viewController1 = [self.storyboard instantiateViewControllerWithIdentifier:@"vc1"];
_container.view = viewController1.view;
selectedViewController = viewController1;
}
到fire视图确实出现了,调用了removeChildViewController,didMoveToParent,addChildViewController,didMoveToParent
答案 4 :(得分:0)
我使用UITabBarController让它工作。为了使用自定义选项卡,我不得不继承TabBarController,并在代码中将按钮添加到控制器。然后,我会在按钮上收听点击事件,并为每个标签设置selectedIndex
。
这很简单,但是我的故事板中有很多垃圾,就像3个标签一样简单。