如何通过工具栏按钮替换容器视图?

Posted

技术标签:

【中文标题】如何通过工具栏按钮替换容器视图?【英文标题】:How to replace container view via toolbar buttons? 【发布时间】:2014-04-04 17:58:16 【问题描述】:

我想创建一个 UI,其中有一个导航栏及其按钮,其下方有一个工具栏,两者始终可见。然后,我希望底部有一个工具栏,当您点击按钮时,它将替换屏幕中间可见的内容。我会使用UITabBarController,但我不想要下面的文本标签,也不想要图标的图像 - 按钮将是一个 unicode 字符。它们应该是灰色的,然后在选择一个时用浅色填充。我在想这样做的方法是在点击按钮时应用色调,但由于条形按钮没有粘性“选定状态”,我不知道该怎么做。

我也不确定如何替换中间的内容。我在想我应该创建一个容器,然后从每个将performSegueWithIdentifier 的按钮创建一个操作方法到一个包含不同内容的不同容器。但是只能嵌入一个视图控制器——我不能从容器中创建多个 segue。我基本上是在尝试用较小的按钮模拟一个标签栏控制器,没有标签,并且屏幕上的整个内容不会在点击按钮时被替换。

我该怎么做呢?我想在 Interface Builder 中完成基本布局,但当然需要一些代码。谢谢!

这基本上是我想要实现的目标:

【问题讨论】:

请使用xcode标签仅用于与IDE相关的问题。 【参考方案1】:

这是我过去的做法。代码位于自定义容器控制器中,该控制器是嵌入在故事板的容器视图中的控制器。因此,在 viewDidAppear: 中,我将第一个控制器添加为子级,并在单击按钮时调用 switchToNewView:。

@implementation ContainerController


- (void)viewDidAppear:(BOOL)animated 
    [super viewDidAppear:animated];
    UIViewController *initial = [self.storyboard instantiateViewControllerWithIdentifier:@"InitialVC"];
    [self addChildViewController:initial];
    [self.view addSubview:initial.view];
    self.currentController = initial;
    [self constrainViewEqual:self.currentController];


-(IBAction)switchToNewView 
    UIViewController *sub = [self.storyboard instantiateViewControllerWithIdentifier:@"SubstituteVC"];
    [self addChildViewController:sub];
    sub.view.frame = self.view.bounds;
    [self moveToNewController:sub];


-(void)moveToNewController:(UIViewController *) newController 
    [self.currentController willMoveToParentViewController:nil];
    [self transitionFromViewController:self.currentController toViewController:newController duration:.6 options:UIViewAnimationOptionTransitionCrossDissolve animations:^
         completion:^(BOOL finished) 
             [self.currentController removeFromParentViewController];
             [newController didMoveToParentViewController:self];
             self.currentController = newController;
             [self constrainViewEqual:self.currentController];
         ];

constrainViewEqual 是我为控制器视图添加约束的类别方法。看起来是这样的,

-(void)constrainViewEqual:(UIViewController *) vc 
    [vc.view setTranslatesAutoresizingMaskIntoConstraints:NO];
    NSLayoutConstraint *con1 = [NSLayoutConstraint constraintWithItem:self.view attribute:NSLayoutAttributeCenterX relatedBy:0 toItem:vc.view attribute:NSLayoutAttributeCenterX multiplier:1 constant:0];
    NSLayoutConstraint *con2 = [NSLayoutConstraint constraintWithItem:self.view attribute:NSLayoutAttributeCenterY relatedBy:0 toItem:vc.view attribute:NSLayoutAttributeCenterY multiplier:1 constant:0];
    NSLayoutConstraint *con3 = [NSLayoutConstraint constraintWithItem:self.view attribute:NSLayoutAttributeWidth relatedBy:0 toItem:vc.view attribute:NSLayoutAttributeWidth multiplier:1 constant:0];
    NSLayoutConstraint *con4 = [NSLayoutConstraint constraintWithItem:self.view attribute:NSLayoutAttributeHeight relatedBy:0 toItem:vc.view attribute:NSLayoutAttributeHeight multiplier:1 constant:0];
    NSArray *constraints = @[con1,con2,con3,con4];
    [self.view addConstraints:constraints];

【讨论】:

这看起来是个不错的解决方案。我决定采取不同的方法,所以我没有尝试,否则我会选择这个作为答案。 ;)【参考方案2】:

我已经实现了我想要的行为。

这不是一个特别干净的解决方案,但它确实提供了一个额外的好处:能够在底部的选项卡之间滑动。

基本上:

    我创建了一个填充整个屏幕的容器视图,其中包含一个页面视图控制器 我删除了页面控件(没有实现委托方法,所以您看不到点) 页面是来自可重用视图控制器的 5 个集合视图 我实现了在页面完全转换时调用的委托方法,然后在循环其他按钮将色调重置为灰色之后,我更改了底部相应栏按钮的色调颜色(默认为灰色) . 如果用户点击条形按钮而不是滑动,我会为页面视图控制器设置视图控制器,然后更新色调。

这运行良好,但代码不是很好。

我可能会做的另一件事是覆盖栏按钮突出显示状态。 当用户突出显示一个标签栏按钮时,标签栏按钮不应变亮。

有趣的是,不允许在页面之间滑动很容易,只需删除页面视图控制器数据源方法即可。然后它的行为就像一个真正的选项卡式界面。不过,我非常喜欢滑动和点击的灵活性。

【讨论】:

【参考方案3】:

这不是一个完整的答案,只是我目前可以提供的一点帮助


您可以将UIButton 用作UIBarButtonItem 对象的customView,然后利用UIButton 对象的highlighted 和/或selected 状态。 另外...如果您打算使用 Unicode 而不是图像,那么 tintColor 并不重要。 您不妨简单地更改按钮titleLabeltextColor取决于UIControlStateNormal

示例:

- (void)testMethod
    
    UIToolbar *tbTest = [[UIToolbar alloc] init];
    [tbTest setFrame:CGRectMake(0, 100, 320, 44)];
    [self.view addSubview:tbTest];

    UIButton *btnTest = [UIButton buttonWithType:UIButtonTypeSystem];
    [btnTest setFrame:CGRectMake(0, 0, 100, 44)];
    [btnTest setTintColor:[UIColor blueColor]];

    [btnTest setTitle:@"Normal" forState:UIControlStateNormal];
    [btnTest setTitleColor:[UIColor redColor] forState:UIControlStateNormal];

    [btnTest setTitle:@"Highlighted" forState:UIControlStateHighlighted];
    [btnTest setTitleColor:[UIColor orangeColor] forState:UIControlStateHighlighted];

    [btnTest setTitle:@"Selected" forState:UIControlStateSelected];
    [btnTest setTitleColor:[UIColor purpleColor] forState:UIControlStateSelected];

    [btnTest addTarget:self action:@selector(doSomething:) forControlEvents:UIControlEventTouchUpInside];

    UIBarButtonItem *btn2Test = [[UIBarButtonItem alloc] initWithCustomView:btnTest];

    [tbTest setItems:@[btn2Test]];


-(void)doSomething:(UIButton *)sender

    [sender setSelected:!sender.selected];


关于重新创建tabBar,我只能这样想:

    将类似UITabBar 的视图固定到底部 用空的UIView 对象填充顶部空间 将标签viewControllers 作为childViewControllers 添加到此UIView

此外,您可以查看我最近开始在 github 上创作的一个有点相似的组件:https://github.com/staticVoidMan/SVMSlidingTabBar 1. 非故事板(但不太难移植) 2. 目前仅支持标签按钮的图像(但感谢您的想法

【讨论】:

我决定采用不同的方法,但你让我想到了突出的色调等。 :) @Joey :太好了,只要它做你想做的事 :)

以上是关于如何通过工具栏按钮替换容器视图?的主要内容,如果未能解决你的问题,请参考以下文章

如何在数据表的表格工具中用图标替换按钮?

如何在模态视图的工具栏上添加标题和完成按钮

从子视图控制器返回到容器

iOS:防止通过禁用的工具栏按钮点击

Android Studio:如何防止工具栏中的向上按钮将子视图向右推?

如何在工具条按钮位置打开表单