Animate ratio changes.
MODIFY
swift/Samples/SplitScreenContainer/DemoApp/BaseScreen.swift
swift/Samples/SplitScreenContainer/DemoApp/BaseScreen.swift
@@ -20,6 +20,7 @@ import WorkflowUI
struct BaseScreen: Screen {
let title: String
let backgroundColor: UIColor
+ let viewTapped: () -> Void
}
@@ -35,6 +36,7 @@ extension ViewRegistry {
fileprivate final class BaseScreenViewController: ScreenViewController<BaseScreen> {
private lazy var titleLabel: UILabel = .init()
+ private lazy var tapGestureRecognizer: UITapGestureRecognizer = .init()
required init(screen: BaseScreen, viewRegistry: ViewRegistry) {
super.init(screen: screen, viewRegistry: viewRegistry)
@@ -45,6 +47,9 @@ fileprivate final class BaseScreenViewController: ScreenViewController<BaseScree
override func viewDidLoad() {
super.viewDidLoad()
+ tapGestureRecognizer.addTarget(self, action: #selector(viewTapped))
+ view.addGestureRecognizer(tapGestureRecognizer)
+
titleLabel.translatesAutoresizingMaskIntoConstraints = false
titleLabel.textAlignment = .center
view.addSubview(titleLabel)
@@ -63,5 +68,10 @@ fileprivate final class BaseScreenViewController: ScreenViewController<BaseScree
view.backgroundColor = screen.backgroundColor
titleLabel.text = screen.title
}
+
+ @objc
+ private func viewTapped() {
+ screen.viewTapped()
+ }
}

MODIFY
swift/Samples/SplitScreenContainer/DemoApp/DemoWorkflow.swift
swift/Samples/SplitScreenContainer/DemoApp/DemoWorkflow.swift
@@ -31,10 +31,10 @@ struct DemoWorkflow: Workflow {
extension DemoWorkflow {
- typealias State = Void
+ typealias State = Int
func makeInitialState() -> State {
- return ()
+ return 1
}
func workflowDidChange(from previousWorkflow: DemoWorkflow, state: inout State) {
@@ -42,6 +42,25 @@ extension DemoWorkflow {
}
+// MARK: Actions
+
+extension DemoWorkflow {
+ enum Action: WorkflowAction {
+ typealias WorkflowType = DemoWorkflow
+
+ case viewTapped
+
+ func apply(toState state: inout DemoWorkflow.State) -> Never? {
+ switch self {
+ case .viewTapped:
+ state += 1
+ }
+
+ return nil
+ }
+ }
+}
+
// MARK: Rendering
@@ -49,12 +68,15 @@ extension DemoWorkflow {
typealias Rendering = SplitScreenContainerScreen
+ private static let sizes: [CGFloat] = [.quarter, .third, .half, 0.75]
+
func render(state: State, context: RenderContext<DemoWorkflow>) -> Rendering {
+ let sink = context.makeSink(of: Action.self)
return SplitScreenContainerScreen(
- leftScreen: BaseScreen(title: "Left screen", backgroundColor: .red),
- rightScreen: BaseScreen(title: "Right screen", backgroundColor: .green),
- ratio: .third
+ leftScreen: BaseScreen(title: "Left screen", backgroundColor: .red, viewTapped: { sink.send(.viewTapped) }),
+ rightScreen: BaseScreen(title: "Right screen", backgroundColor: .green, viewTapped: { sink.send(.viewTapped) }),
+ ratio: DemoWorkflow.sizes[state % DemoWorkflow.sizes.count]
)
}

MODIFY
swift/Samples/SplitScreenContainer/Sources/SplitScreenContainerViewController.swift
swift/Samples/SplitScreenContainer/Sources/SplitScreenContainerViewController.swift
@@ -29,6 +29,7 @@ final class SplitScreenContainerViewController: ScreenViewController<SplitScreen
private var leftContentViewController: ScreenViewController<AnyScreen>? = nil
private lazy var leftContainerView: UIView = .init()
+ private var leftContainerViewWidthConstraint: NSLayoutConstraint?
private lazy var separatorView: UIView = .init()
@@ -75,6 +76,10 @@ final class SplitScreenContainerViewController: ScreenViewController<SplitScreen
} else {
self.rightContentViewController = embed(screen.rightScreen, in: rightContainerView)
}
+
+ if (leftContainerViewWidthConstraint?.multiplier != screen.ratio) {
+ updateWidthConstraints(ratio: screen.ratio, animated: true)
+ }
}
private func embed(_ screen: AnyScreen, in containerView: UIView) -> ScreenViewController<AnyScreen> {
@@ -113,7 +118,6 @@ final class SplitScreenContainerViewController: ScreenViewController<SplitScreen
leftContainerView.leftAnchor.constraint(equalTo: view.leftAnchor),
leftContainerView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
leftContainerView.rightAnchor.constraint(equalTo: separatorView.leftAnchor),
- leftContainerView.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: screen.ratio),
separatorView.topAnchor.constraint(equalTo: view.topAnchor),
separatorView.widthAnchor.constraint(equalToConstant: 1.0),
@@ -124,5 +128,25 @@ final class SplitScreenContainerViewController: ScreenViewController<SplitScreen
rightContainerView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
rightContainerView.rightAnchor.constraint(equalTo: view.rightAnchor),
])
+
+ updateWidthConstraints(ratio: screen.ratio, animated: false)
+ }
+
+ private func updateWidthConstraints(ratio: CGFloat, animated: Bool) {
+ guard animated else {
+ self.leftContainerViewWidthConstraint = self.leftContainerView.widthAnchor.constraint(equalTo: self.view.widthAnchor, multiplier: ratio)
+ self.leftContainerViewWidthConstraint?.isActive = true
+ return
+ }
+
+ view.layoutIfNeeded()
+ UIView.animate(withDuration: 0.2) {
+ self.leftContainerViewWidthConstraint?.isActive = false
+
+ self.leftContainerViewWidthConstraint = self.leftContainerView.widthAnchor.constraint(equalTo: self.view.widthAnchor, multiplier: ratio)
+ self.leftContainerViewWidthConstraint?.isActive = true
+
+ self.view.layoutIfNeeded()
+ }
}
}

Animate ratio changes.