I am trying to have a viewController with two UIView
s side to side for iPad screens. The left view will have a tableview while the right view will be the contents of the selected tableview cell. Similar to how the iPad mail app is (which uses a UISplitViewController
) but in portrait orientation the left view (the tableview) should stay there and not go away (UISplitViewController
makes it go away).
I was able to get this to work by just using constraints, but in addition the side-to-side views, I need a vertical bar between the views where I can shift the views to either side to see more of the left or right view. This bar is similar to the bar in the Notability app when looking at two notes together (see attached screenshot). When I tried to make the bar move, the constraints restrict me from letting it happen. What is the best way to do this?
Best way to do that would be to not use UISplitViewController
.
Instead, just use full-screen UIViewController
as a container, have two container views separated by the bar
inside, add your table view controller and details controller as child view controllers into it.
You can align bar
horizontally to white superview.center.x
(let's name this constraint barAlignToSuperviewCenterConstraint
), you can easily move it by changing constant of the constraint to the offset from the center.
To do so,
UIPanGestureRecognizer
to the superview of the bar which is also superview for the panels (let's name it barDragRecognizer
).in the recognizer's callback, when pan recognizer is in state .began
, set its translation to the current value of barAlignToSuperviewCenterConstraint.constant
:
barDragRecognizer.setTranslation(CGPoint(x: barAlignToSuperviewCenterConstraint.constant, y: 0) in: bar.superview)
in the recognizer's callback, when pan recognizer is in one of the states .changed
, .ended
, .cancelled
, set value of the constraint's constant to recognizer's translation value:
barAlignToSuperviewCenterConstraint.constant = barDragRecognizer.translation(in: bar.superview).x;
To make your recognizer receive touches only from the bar, assign your view controller as delegate of the recognizer and implement the following:
func gestureRecognizer(UIGestureRecognizer recognizer, shouldReceive: UITouch touch) -> Bool {
let barExtendedBounds = bar.bounds.insetBy(dx: -20, dy: 0)
return (recognizer == barDragRecognizer && barExtendedBounds.constains(touch.location(in: bar)))
}