Skip to content

Commit

Permalink
Fitting size with axis
Browse files Browse the repository at this point in the history
  • Loading branch information
ra1028 committed Oct 25, 2019
1 parent a7a9e47 commit 7bb0b2f
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 35 deletions.
7 changes: 7 additions & 0 deletions Examples/Example-iOS/Sources/Kyoto/KyotoViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,11 @@ final class KyotoViewController: UIViewController {
})
}
}

override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()

// This solves sizing bug in MagazineLayout.
collectionView.performBatchUpdates(nil)
}
}
13 changes: 0 additions & 13 deletions Sources/ComponentWrapper/ComponentWrapping.swift
Original file line number Diff line number Diff line change
Expand Up @@ -143,16 +143,3 @@ public extension ComponentWrapping {
wrapped.contentDidEndDisplay(content)
}
}

#if canImport(SwiftUI) && canImport(Combine)

import SwiftUI

@available(iOS 13.0, *)
public extension ComponentWrapping where Wrapped: View {
var body: some View {
wrapped.body
}
}

#endif
85 changes: 63 additions & 22 deletions Sources/SwiftUISupport/ComponentSwiftUISupport.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,26 +6,32 @@ import SwiftUI
public extension Component where Self: View {
/// Declares the content and behavior of this view.
var body: some View {
ComponentView(self)
sizeFitting(.vertical)
}

func sizeFitting(_ axis: Axis? = nil) -> some Component & View {
SizeFittingComponentView(self, axis: axis)
}
}

@available(iOS 13.0, *)
private struct ComponentView<C: Component>: View {
var component: C
var proxy = ComponentViewProxy()
private struct SizeFittingComponentView<Wrapped: Component>: View, ComponentWrapping {
var wrapped: Wrapped
var axis: Axis?

@State var bounds: CGRect?
private var proxy = ComponentViewProxy()
@State private var bounds: CGRect?

init(_ component: C) {
self.component = component
public init(_ wrapped: Wrapped, axis: Axis?) {
self.wrapped = wrapped
self.axis = axis
}

var body: some View {
let idealSize = self.idealSize()
return ComponentRepresenting(component: component, proxy: proxy)
.frame(idealWidth: idealSize?.width)
.frame(height: idealSize?.height)
let preferredSize = self.preferredSize()
return ComponentRepresenting(component: AnyComponent(wrapped), proxy: proxy)
.frame(idealWidth: preferredSize.idealWidth, idealHeight: preferredSize.idealHeight)
.frame(width: preferredSize.fixedWidth, height: preferredSize.fixedHeight)
.clipped()
.onAppear { self.proxy.uiView?.contentWillDisplay() }
.onDisappear { self.proxy.uiView?.contentDidEndDisplay() }
Expand All @@ -37,24 +43,59 @@ private struct ComponentView<C: Component>: View {
}

@available(iOS 13.0, *)
extension ComponentView {
func idealSize() -> CGSize? {
private extension SizeFittingComponentView {
struct Size {
var idealWidth: CGFloat?
var idealHeight: CGFloat?
var fixedWidth: CGFloat?
var fixedHeight: CGFloat?
}

func preferredSize() -> Size {
guard let bounds = bounds else {
return nil
return Size()
}

if let referenceSize = component.referenceSize(in: bounds) {
return referenceSize
}
else {
return proxy.uiView?.systemLayoutSizeFitting(
let referenceSize = wrapped.referenceSize(in: bounds)

switch axis {
case .none:
let size = referenceSize ?? proxy.uiView?.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize)

return Size(
fixedWidth: size?.width,
fixedHeight: size?.height
)

case .horizontal:
let size = referenceSize ?? proxy.uiView?.systemLayoutSizeFitting(
CGSize(
width: UIView.layoutFittingCompressedSize.width,
height: bounds.size.height
),
withHorizontalFittingPriority: .fittingSizeLevel,
verticalFittingPriority: .required
)

return Size(
idealHeight: size?.height,
fixedWidth: size?.width
)

case .vertical:
let size = referenceSize ?? proxy.uiView?.systemLayoutSizeFitting(
CGSize(
width: bounds.size.width,
height: UIView.layoutFittingCompressedSize.height
),
withHorizontalFittingPriority: .required,
verticalFittingPriority: .fittingSizeLevel
)

return Size(
idealWidth: size?.width,
fixedHeight: size?.height
)
}
}
}
Expand All @@ -63,8 +104,8 @@ private struct BoundsPreferenceKey: PreferenceKey {
static func reduce(value: inout CGRect?, nextValue: () -> CGRect?) {}
}

private struct ComponentRepresenting<C: Component>: UIViewRepresentable {
var component: C
private struct ComponentRepresenting: UIViewRepresentable {
var component: AnyComponent
var proxy: ComponentViewProxy

func makeUIView(context: Context) -> UIComponentView {
Expand All @@ -73,7 +114,7 @@ private struct ComponentRepresenting<C: Component>: UIViewRepresentable {

func updateUIView(_ uiView: UIComponentView, context: Context) {
proxy.uiView = uiView
uiView.render(component: AnyComponent(component))
uiView.render(component: component)
}
}

Expand Down

0 comments on commit 7bb0b2f

Please sign in to comment.