0
votes

I have a UIViewController with a container view and I'm using auto layout. I have programmatically added another view controller as a child and added its view as a subview and set the view frame to the same as the container view. Everything is fine and when I animate a change to the container view, it adjusts correctly. How do I get the view of the child view controller to resize?

The child view controller is actually a navigation controller (called current_controller) created programmatically and has a root view controller which uses auto layout. Here is the method I'm using (it's in Ruby as I'm using RubyMotion but you'll get the idea). I have tried adding the three lines below to the completion block but they don't have any effect.

  def shortcuts_hidden (hide)
    NSLog("setting shortcuts hidden to #{hide}")
    shortcuts_constraint.constant = hide ? shortcuts_view.frame.size.height : 0    
    UIView.animateWithDuration(
      0.25,
      animations: lambda {
        self.view.layoutIfNeeded
      },
      completion: lambda { |completed|
        current_controller.view.frame.size.height = container_view.frame.size.height
        current_controller.view.layoutIfNeeded
        current_controller.viewControllers[0].view.layoutIfNeeded
      }
    )
  end

Update with "solution":

  def configure_constraints_for_view(controller_view)
    [NSLayoutAttributeLeft, NSLayoutAttributeRight, NSLayoutAttributeTop, NSLayoutAttributeBottom].each do |attribute_name|
      self.view.addConstraint(
        NSLayoutConstraint.constraintWithItem(
          controller_view,
          attribute: attribute_name,
          relatedBy: NSLayoutRelationEqual,
          toItem: container_view,
          attribute: attribute_name,
          multiplier: 1.0,
          constant: 0
        )
      )
    end
  end

and

  def select_view_controller(index)
    if current_controller
      current_controller.removeFromParentViewController
      current_controller.view.removeFromSuperview
    end
    controller = view_controllers[index].build_menu_item
    controller.selected_from_menu = true
    @current_controller = UINavigationController.alloc.initWithRootViewController(controller)
    self.addChildViewController(current_controller)
    self.view.addSubview(current_controller.view)
    current_controller.view.translatesAutoresizingMaskIntoConstraints = false
    configure_constraints_for_view(current_controller.view)
    current_controller.didMoveToParentViewController(self)
  end
2

2 Answers

3
votes

When you add the child's view, you should give it constraints to make it the same size as the container view instead of setting its frame. If you do that, then it will automatically adjust when the container view's bounds change.

2
votes

Preamble: That Ruby looks odd, but I don't know anything about RubyMotion. In iOS, you can't set the height of a view directly, you have to set its frame all at once. I'm going to assume that RubyMotion just abstracts it and allows you to do ridiculous things like this.


It looks like you're modifying the frame of your current_controller.view, but you've not modified the frame of the child view controllers's view.

    current_controller.view.frame.size.height = container_view.frame.size.height
    current_controller.view.layoutIfNeeded
    current_controller.viewControllers[0].view.frame.size.height = container_view.frame.size.height
    current_controller.viewControllers[0].view.layoutIfNeeded

I don't know if that is the measurement you want, but it should (probably) at least change something.