Search code examples
iosuiviewcontrolleruikitrubymotion

Child view controller does not auto layout when the parent UIViewController adjusts the size of the container view


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

Solution

  • 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.