【问题标题】:iOS equivalent for Android View.GONE visibility modeiOS 等效于 Android View.GONE 可见性模式
【发布时间】:2013-07-26 00:14:35
【问题描述】:

我正在为 iOS 开发一个应用程序,并且我正在使用启用了 AutoLayout 的 Storyboard。我的一个视图控制器有一组 4 个按钮,在某些情况下我想让第一个按钮消失。

如果我使用setHidden:TRUE 方法,UIButton 会变得不可见,但它仍然明显占用视图中的空间,结果是一个“洞”,我无法填充它,使剩余的 UIButton 浮向主视图的顶部。

在 Android 中,我会简单地使用 View.GONE 而不是 View.INVISIBLE,但在 iOS 中,我坚持这种行为,我不想相信唯一的解决方案是手动(是的,我的意思是通过编程)将剩余的元素移到顶部。

我以为我可以通过设置某种约束来让一切都像在 Android 中一样自动化,但我没有运气。

在我关闭自动布局之前,有人可以指出正确的方向吗?

我正在使用 IB,但我也对程序化的东西感到满意。

更新:

将组件高度设置为 0 也无济于事。

我尝试过这样的事情:

UIButton *b;
CGRect frameRect = b.frame;
frameRect.size.height = 0;
b.frame = frameRect;

【问题讨论】:

  • 按钮的高度设置为零怎么样?
  • 我试过这样的:UIButton * b; CGRect frameRect = b.frame; frameRect.size.height = 0; b.frame = frameRect;没有运气:(
  • 我知道这是一个非常老的问题,但是如果您使用自动布局,将框架设置为 0 的更新将无济于事。您必须将高度约束设置为 0

标签: iphone ios interface-builder visibility autolayout


【解决方案1】:

在 iOS 上实现 Androids.GONE 功能是使用 UIStackView。之后按位置隐藏孩子。 (Apples documentation)

SWIFT 4:

let firstView = cell.rootStackView.arrangedSubviews[0]
    firstView.isHidden = true // first view gone

这是一个表格单元格示例,只需将两个内部都放入 Stack view 并获取 GONE 孩子的项目。

【讨论】:

    【解决方案2】:

    您可以将视图分组到堆栈视图下。然后,当您隐藏特定视图时,其余视图将自动移动以填充空间。

    您可能需要查看有关堆栈视图的 Apple 文档: https://developer.apple.com/reference/uikit/uistackview

    或在线教程如:https://www.appcoda.com/stack-views-intro/

    【讨论】:

      【解决方案3】:

      这个问题已经很老了,但我发现的最重要的事情是设置额外的约束(所以“消失”视图周围的视图知道一旦丢失该做什么)

      A  which you want to be     A
      |  after setting B to gone  |
      B                           C
      |                               
      C                               
      
      1. 设置从 C 到 A 的较低优先级 (750) 约束。
      2. 将 B 的顶部和底部约束(如果您希望视图水平折叠,则添加左右)到 NSLayoutConstraint 数组 bConstraints。通过以下方式执行此操作:
        1. 控制单击并从约束拖动到 ViewController
        2. 将连接从 Outlet 更改为 Outlet Collection
        3. 名字输入bConstraints
        4. 点击连接。这将在您的 ViewController 中创建一个 @IBOutlet var bConstraints: [NSLayoutConstraint]!
        5. 要添加其他约束:从 Storyboard 中的约束拖动到 @IBOutlet 变量名
      3. 然后隐藏B

        B.hidden = true
        NSLayoutConstraint.deactivateConstraints(bConstraints)
        
      4. 取消隐藏

        B.hidden = false
        NSLayoutConstraint.activateConstraints(bConstraints)
        

      显然,您拥有的视图越多,情况就越复杂,因为您需要每个视图的附加约束

      【讨论】:

      • 如果你解释了为什么你不能实现会更有帮助
      • 第二点。我虽然在 Xamarin 工作。仍然没有找到解决这个问题的方法。不知道你应该如何构造一个带有 B 约束的 NSLayoutConstraint 数组。我认为它是以编程方式完成的,很高兴看到它的代码。在我看来,你的方法是解决这个问题最合理的方法,但仅使用伪代码并不容易实现
      • 我没有使用过 Xamarin。在 XCode 中完成的方式是:按住 ctrl 单击并从约束拖动到 ViewController(这类似于您在 xcode 中创建 IBOutlet 的方式)。在出现的弹出窗口(类似于i.stack.imgur.com/JegLK.png)中,将“连接”下拉菜单从Outlet 更改为Outlet Collection。对于附加约束,ctrl 直接拖动到变量名。我可以在今天晚些时候(约 8 小时)上传截图
      • 所以 NSLayoutConstraint 数组是插座集合,这里有点迷路了哈哈,感谢您花时间回答我的问题 :)
      • 是的,我会更新答案以更清楚。那么该解决方案对您有用吗?
      【解决方案4】:

      关于这个问题的所有答案都是低效的。 在 iOS 上等同于 Android setVisibility:Gone 方法的最佳方法是 StackView 首先选择组件,然后在编辑器中,嵌入,堆栈视图,

      用 IBOutlet 连接新的堆栈视图,然后:

      隐藏:

      UIView * firstView = self.svViewFontConfigure.arrangedSubviews[0];
              firstView.hidden = YES;
      

      可见性:

      UIView * firstView = self.svViewFontConfigure.arrangedSubviews[0];
              firstView.hidden = NO;
      

      与使用堆栈视图一样,所有约束都将保留!

      Document

      【讨论】:

      • 实际上似乎是一个非常好的解决方案,但值得注意的是它需要iOS9+。
      • 我使用了您出色的解决方案(为您+1,非常感谢!!)但我通过 IBOutlet 直接连接了我想要显示和隐藏的视图,因此我只需输入一行代码! :)
      • 这个答案实际上不正确。 Android View.GONE 删除 UI 上的视图。例如,如果您设置 View.GONE 一个元素,则该视图下方的视图将向上移动。所以你的建议只是隐藏了等于 View.HIDE 的视图。看看这个答案:stackoverflow.com/questions/11556607/…
      • 我没有在 android api 上搜索...但我是移动开发人员,所以我知道机械师...在带有布尔标志的 Android 中,视图是否可见(消失,可见)如果它从 ui 中删除将很难再次添加...但在 ios 中,它在布局中但没有空格....此外,还有官方的 ios 隐藏属性发生...UIStackview 隐藏属性,如 android View.Gone
      【解决方案5】:

      为您的视图添加高度约束,如下所示:

      然后在 viewController 文件中为高度约束创建一个出口,如下所示:

      & 然后在您的 viewDidLoad 方法中将约束高度更改为 0,如下所示:

      override func viewDidLoad() {
          super.viewDidLoad()
      nsLcButtonHeight.constant = 0
      }
      

      【讨论】:

      • 恒定高度很糟糕,我使用相等的高度和乘数,例如占父视图的 25%,有什么例子吗?
      【解决方案6】:

      我在自定义 UIView 实现中添加了一个名为“visible”的新属性,当它设置为 false 时,会添加一个约束以折叠视图(我只添加了一个宽度约束,因为我的列表是水平的,但最好的方法可能是添加高度约束为 0 以及)。

      var visible:Bool = true{
              didSet{
                  if(visible){
                      clipsToBounds = false;
                      removeConstraint(hideConstraint!)
                  }else{
                      clipsToBounds = true
                      addConstraint(hideConstraint!)
                  }
              }
          }
      

      需要在视图上初始化零宽度约束,并将其添加为字段:

      private var hideConstraint:NSLayoutConstraint?
      
      
      func someInitFunction(){
          hideConstraint = NSLayoutConstraint(item: self, attribute: NSLayoutAttribute.Width, relatedBy: NSLayoutRelation.Equal, toItem: nil, attribute: NSLayoutAttribute.NotAnAttribute, multiplier: 1.0, constant: 0.0)
          ...
      }
      

      【讨论】:

        【解决方案7】:

        根据 Deniz 提供的答案,这里是使用 Swift 中的约束的解决方案

        例如:如果您有 3 个视图,A_view B_view 和 C_view 以该顺序垂直对齐,并且您想“隐藏”B 并调整差异,请添加约束

        B_view.removeFromSuperView()
        var constr = NSLayoutConstraint(item: C_view, 
                                        attribute: NSLayoutAttribute.Top, 
                                        relatedBy: NSLayoutRelation.Equal, 
                                        toItem: A_view, 
                                        attribute: NSLayoutAttribute.Bottom,
                                        multiplier: 1,
                                        constant: 20)
        view.addConstraint(constr)
        

        常量是(在这种情况下)C_view 和 A_view 之间的垂直空间量

        【讨论】:

          【解决方案8】:

          setHidden:TRUE/FALSE 最接近 Android View.GONE/VISIBLE。

          如果不可见,视图不一定会占用空间!

          我制作了一个类似于 ComboBox 的 ListView,它位于其他视图之上。我只在选择时可见:

          【讨论】:

          • 你忘了在android中我们也有view.invisible...view.gone和setHidden不相似...它的view.invisible类似于setHidden
          【解决方案9】:

          您还可以清除页面,或者至少清除页面的某些单元格,然后重新定义整个内容。它速度快而且效果很好。我没有编写代码,但在我正在处理的这个预先存在的项目中找到了它。创建ManagementTableSectionManagementTableCell 类来管理它。抱歉,我无法提供更好的定义代码。

          【讨论】:

            【解决方案10】:

            【讨论】:

              【解决方案11】:

              添加一个将视图高度设置为 0 的约束(NSLayoutAttributeHeight)对我有用:

              [self.view addConstraint:[NSLayoutConstraint constraintWithItem:self.captchaView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:0]];
              

              【讨论】:

              • Swift 版本:self.view.addConstraint(NSLayoutConstraint(item: self.captchaView, attribute: .Height, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1.0, constant: 0))
              • 这应该是答案
              • 如果我不知道所需视图的实际高度(例如稍后渲染的容器视图)怎么办?
              • 非常感谢您的精彩回答!因为有人可能需要它。我收到一个错误Unable to simultaneously satisfy constraints。虽然我已经对视图有限制。我通过stackoverflow.com/a/38625419/1270901解决它
              • @iStar 我使用了相同的代码,但它不起作用...stackoverflow.com/questions/45454992/…
              【解决方案12】:

              正如我的研究表明,即使是 AutoLayout 也无法为您提供帮助。您必须手动替换受可选显示组件影响的视图(在我的情况下,所有视图都位于可选视图的底部,但我相信您可以调整它以处理可选按钮右侧的所有按钮):

              - (IBAction)toggleOptionalView:(id)sender {
                  if (!_expanded) {
                      self.optionalView.frame = CGRectMake(self.optionalView.frame.origin.x, self.optionalView.frame.origin.y, self.optionalView.frame.size.width, _optionalHeight);
                      self.bottomView.frame = CGRectMake(self.bottomView.frame.origin.x, self.bottomView.frame.origin.y+_optionalHeight, self.bottomView.frame.size.width, self.bottomView.frame.size.height);
                      _expanded = YES;
                  } else {
                      self.optionalView.frame = CGRectMake(self.optionalView.frame.origin.x, self.optionalView.frame.origin.y, self.optionalView.frame.size.width, 0);
                      self.bottomView.frame = CGRectMake(self.bottomView.frame.origin.x, self.bottomView.frame.origin.y-_optionalHeight, self.bottomView.frame.size.width, self.bottomView.frame.size.height);
                      _expanded = NO;
              
                  }
              }
              

              建议不要对可选组件的高度/宽度进行硬编码,否则每次编辑 XIB/Storyboard 时代码都会中断。我在 viewDidLoad 中设置了一个 float _optionalHeight 字段,所以它始终是最新的。

              【讨论】:

                【解决方案13】:

                1) 如果您的按钮是垂直放置的,那么您必须将 height 设置为 0,如果是水平放置的按钮,请尝试将 width 设置为 0,或者您可以将两者都设置为 0。

                2) 你可以尝试这种将button2 设置在button1 之上的方法:

                - (void)viewDidLoad
                {
                [super viewDidLoad];
                
                UIButton *button1 = [UIButton buttonWithType:UIButtonTypeRoundedRect];
                [button1 setTitle:@"hello" forState:UIControlStateNormal];
                
                UIButton *button2 = [UIButton buttonWithType:UIButtonTypeRoundedRect];
                [button2 setTitle:@"world" forState:UIControlStateNormal];
                
                [button1 sizeToFit]; [button2 sizeToFit];
                [button2 setFrame:CGRectMake(button1.frame.origin.x, button1.frame.origin.y, button2.frame.size.width, button2.frame.size.height)];
                
                [self.view addSubview:button1];
                [self.view addSubview:button2];
                
                }
                

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2012-03-25
                  • 2019-10-14
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多