fix: move presentation detents settings to modal view controller appearance, force use nan for undefined layout dimension, fix related layout issues
This commit is contained in:
parent
8007532351
commit
35ec61a0ee
|
|
@ -5,8 +5,8 @@
|
|||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/Alamofire/Alamofire.git",
|
||||
"state" : {
|
||||
"revision" : "f96b619bcb2383b43d898402283924b80e2c4bae",
|
||||
"version" : "5.4.3"
|
||||
"revision" : "bc268c28fb170f494de9e9927c371b8342979ece",
|
||||
"version" : "5.7.1"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
@ -32,8 +32,8 @@
|
|||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/petropavel13/Cursors",
|
||||
"state" : {
|
||||
"revision" : "a1561869135e72832eff3b1e729075c56c2eebf6",
|
||||
"version" : "0.5.1"
|
||||
"revision" : "52f27b82cb1cbbc2b5fd09514c48b9c75e3b0300",
|
||||
"version" : "0.6.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
@ -50,8 +50,8 @@
|
|||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/Moya/Moya.git",
|
||||
"state" : {
|
||||
"revision" : "9b906860e3c3c09032879465c471e6375829593f",
|
||||
"version" : "15.0.0"
|
||||
"revision" : "c263811c1f3dbf002be9bd83107f7cdc38992b26",
|
||||
"version" : "15.0.3"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
@ -59,8 +59,8 @@
|
|||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://git.svc.touchin.ru/TouchInstinct/PanModal",
|
||||
"state" : {
|
||||
"revision" : "be82eddb529faa2bc668230906ec007c53e7b635",
|
||||
"version" : "1.3.0"
|
||||
"revision" : "ced7c1703f90746df0224b6e0d33c146d9ae4284",
|
||||
"version" : "1.3.1"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
@ -77,8 +77,8 @@
|
|||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/ReactiveX/RxSwift.git",
|
||||
"state" : {
|
||||
"revision" : "b4307ba0b6425c0ba4178e138799946c3da594f8",
|
||||
"version" : "6.5.0"
|
||||
"revision" : "9dcaa4b333db437b0fbfaf453fad29069044a8b4",
|
||||
"version" : "6.6.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ extension BaseModalViewController {
|
|||
|
||||
open class BaseAppearance: UIView.BaseAppearance<UIView.DefaultWrappedLayout> {
|
||||
|
||||
public var presentationDetents: [ModalViewPresentationDetent]
|
||||
public var dragViewState: DragView.State
|
||||
public var headerViewState: ModalHeaderView.State
|
||||
public var footerViewState: ModalFooterView<FooterContentView>.State
|
||||
|
|
@ -36,15 +37,26 @@ extension BaseModalViewController {
|
|||
backgroundColor: UIColor = .clear,
|
||||
border: UIViewBorder = .init(),
|
||||
shadow: UIViewShadow? = nil,
|
||||
presentationDetents: [ModalViewPresentationDetent] = [.maxHeight],
|
||||
dragViewState: DragView.State = .hidden,
|
||||
headerViewState: ModalHeaderView.State = .hidden,
|
||||
footerViewState: ModalFooterView<FooterContentView>.State = .hidden) {
|
||||
|
||||
self.presentationDetents = presentationDetents
|
||||
self.dragViewState = dragViewState
|
||||
self.headerViewState = headerViewState
|
||||
self.footerViewState = footerViewState
|
||||
|
||||
super.init(layout: layout, backgroundColor: backgroundColor, border: border, shadow: shadow)
|
||||
super.init(layout: layout,
|
||||
backgroundColor: backgroundColor,
|
||||
border: border,
|
||||
shadow: shadow)
|
||||
}
|
||||
}
|
||||
|
||||
public final class DefaultAppearance: BaseAppearance, ViewAppearance {
|
||||
public static var defaultAppearance: Self {
|
||||
Self()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -112,7 +112,7 @@ open class BaseModalViewController<ContentView: UIView,
|
|||
let edgeConstraints = EdgeConstraints(leadingConstraint: leadingConstraint,
|
||||
trailingConstraint: trailingConstraint,
|
||||
topConstraint: headerBottomToContentTopConstraint,
|
||||
bottomConstraint: contentView.bottomAnchor.constraint(equalTo: view.bottomAnchor))
|
||||
bottomConstraint: contentViewBottomToSuperviewConstraint)
|
||||
|
||||
let centerXConstraint = contentView.centerXAnchor.constraint(equalTo: view.centerXAnchor)
|
||||
let centerYConstraint = contentView.centerYAnchor.constraint(equalTo: view.centerYAnchor)
|
||||
|
|
@ -153,9 +153,7 @@ open class BaseModalViewController<ContentView: UIView,
|
|||
|
||||
// MARK: - Modal View Controller Configuration
|
||||
|
||||
open var viewControllerAppearance: BaseAppearance {
|
||||
.init(backgroundColor: .white)
|
||||
}
|
||||
public var viewControllerAppearance: BaseAppearance = .init(backgroundColor: .white)
|
||||
|
||||
open var panScrollable: UIScrollView? {
|
||||
contentView as? UIScrollView
|
||||
|
|
@ -167,9 +165,9 @@ open class BaseModalViewController<ContentView: UIView,
|
|||
}
|
||||
}
|
||||
|
||||
open var presentationDetents: [ModalViewPresentationDetent] {
|
||||
[.maxHeight]
|
||||
}
|
||||
public var dimmedView = DimmedView()
|
||||
|
||||
public var showDragIndicator = true
|
||||
|
||||
open var headerViewHeight: CGFloat {
|
||||
let dragViewHeight = getHeight(of: dragView)
|
||||
|
|
@ -346,8 +344,10 @@ open class BaseModalViewController<ContentView: UIView,
|
|||
of: headerViewAppearance.layout.insets)
|
||||
} else {
|
||||
dragViewBottomToHeaderViewTopConstraint.isActive = false
|
||||
topConstraint = dragViewBottomToContentViewTopConstraint
|
||||
topConstant = headerViewAppearance.layout.insets.top
|
||||
topConstraint = headerViewToSuperviewTopConstraint
|
||||
|
||||
let topInset = headerViewAppearance.layout.insets.top
|
||||
topConstant = topInset.isFinite ? topInset : .zero
|
||||
}
|
||||
|
||||
headerViewConstraints.edgeConstraints.topConstraint = topConstraint
|
||||
|
|
@ -380,8 +380,11 @@ open class BaseModalViewController<ContentView: UIView,
|
|||
topConstant = .zero
|
||||
}
|
||||
|
||||
topConstraint.setActiveConstantOrDeactivate(constant: topConstant)
|
||||
contentViewConstraints.activate()
|
||||
contentViewConstraints.edgeConstraints.topConstraint = topConstraint
|
||||
let layout = UIView.DefaultWrappedLayout(insets: .horizontal(.zero)
|
||||
.vertical(top: topConstant)
|
||||
.replacingNan(with: .zero))
|
||||
contentViewConstraints.update(from: layout)
|
||||
}
|
||||
|
||||
private func configureFooterViewLayout() {
|
||||
|
|
@ -389,6 +392,9 @@ open class BaseModalViewController<ContentView: UIView,
|
|||
return
|
||||
}
|
||||
|
||||
contentViewConstraints.edgeConstraints.bottomConstraint.isActive = false
|
||||
contentViewConstraints.edgeConstraints.bottomConstraint = footerViewConstraints.edgeConstraints.topConstraint
|
||||
|
||||
footerViewConstraints.update(from: footerViewAppearance.layout)
|
||||
}
|
||||
|
||||
|
|
@ -423,7 +429,7 @@ open class BaseModalViewController<ContentView: UIView,
|
|||
}
|
||||
|
||||
private func getSortedDetents() -> [ModalViewPresentationDetent] {
|
||||
presentationDetents.uniqued().sorted()
|
||||
viewControllerAppearance.presentationDetents.uniqued().sorted()
|
||||
}
|
||||
|
||||
private func getHeight(of view: UIView) -> CGFloat {
|
||||
|
|
|
|||
|
|
@ -30,6 +30,9 @@ open class DefaultModalWrapperViewController<ContentController: UIViewController
|
|||
self.contentViewController = contentViewController
|
||||
|
||||
super.init(nibName: nil, bundle: nil)
|
||||
|
||||
addChild(contentViewController)
|
||||
contentViewController.didMove(toParent: self)
|
||||
}
|
||||
|
||||
@available(*, unavailable)
|
||||
|
|
@ -38,6 +41,10 @@ open class DefaultModalWrapperViewController<ContentController: UIViewController
|
|||
|
||||
super.init(coder: coder)
|
||||
}
|
||||
|
||||
open override func createContentView() -> UIView {
|
||||
contentViewController.view
|
||||
}
|
||||
}
|
||||
|
||||
public extension UIViewController {
|
||||
|
|
|
|||
|
|
@ -53,16 +53,12 @@ public final class DragView: BaseInitializableView, AppearanceConfigurable {
|
|||
|
||||
public final class Appearance: UIView.BaseWrappedAppearance<UIView.DefaultWrappedLayout>, WrappedViewAppearance {
|
||||
|
||||
public static var defaultAppearance: Appearance {
|
||||
.make { dragView in
|
||||
dragView.backgroundColor = Constants.dragViewBackgroundColor
|
||||
dragView.border = Constants.dragViewBorder
|
||||
|
||||
dragView.layout { layout in
|
||||
layout.size = Constants.dragViewSize
|
||||
layout.insets = .vertical(top: Constants.dragViewTopInset)
|
||||
}
|
||||
}
|
||||
public static var defaultAppearance: Self {
|
||||
Self(layout: DefaultWrappedLayout(insets: .vertical(top: Constants.dragViewTopInset),
|
||||
size: Constants.dragViewSize,
|
||||
centerOffset: .centerHorizontal()),
|
||||
backgroundColor: Constants.dragViewBackgroundColor,
|
||||
border: Constants.dragViewBorder)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -29,6 +29,17 @@ open class ModalFooterView<ContentView: UIView>: ContainerView<ContentView> {
|
|||
|
||||
public enum State {
|
||||
case hidden
|
||||
case presented(BaseWrappedViewHolderAppearance<DefaultWrappedAppearance, DefaultWrappedLayout>)
|
||||
case presented(Appearance)
|
||||
}
|
||||
}
|
||||
|
||||
public extension ModalFooterView {
|
||||
|
||||
final class Appearance: BaseWrappedViewHolderAppearance<DefaultWrappedAppearance, DefaultWrappedLayout>,
|
||||
WrappedViewHolderAppearance {
|
||||
public static var defaultAppearance: Self {
|
||||
Self(layout: DefaultWrappedLayout(insets: .horizontal(.zero).vertical(bottom: .zero),
|
||||
size: .fixedHeight(44)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ open class ModalHeaderView: BaseInitializableView, AppearanceConfigurable {
|
|||
leadingButton.trailingAnchor.constraint(equalTo: trailingButton.leadingAnchor)
|
||||
}()
|
||||
|
||||
public private(set) lazy var leftButtonConstraints: SubviewConstraints = {
|
||||
public private(set) lazy var leadingButtonConstraints: SubviewConstraints = {
|
||||
let edgeConstraints = EdgeConstraints(leadingConstraint: leadingButton.leadingAnchor.constraint(equalTo: leadingAnchor),
|
||||
trailingConstraint: leftTrailingToRightLeadingConstraint,
|
||||
topConstraint: leadingButton.topAnchor.constraint(equalTo: topAnchor),
|
||||
|
|
@ -77,11 +77,10 @@ open class ModalHeaderView: BaseInitializableView, AppearanceConfigurable {
|
|||
trailingButton.leadingAnchor.constraint(equalTo: leadingAnchor)
|
||||
}()
|
||||
|
||||
public private(set) lazy var rightButtonConstraints: SubviewConstraints = {
|
||||
let leadingConstraint = trailingButton.leadingAnchor.constraint(equalTo: leadingAnchor)
|
||||
public private(set) lazy var trailingButtonConstraints: SubviewConstraints = {
|
||||
let trailingConstraint = trailingButton.trailingAnchor.constraint(equalTo: trailingAnchor)
|
||||
|
||||
let edgeConstraints = EdgeConstraints(leadingConstraint: leadingConstraint,
|
||||
let edgeConstraints = EdgeConstraints(leadingConstraint: leftTrailingToRightLeadingConstraint,
|
||||
trailingConstraint: trailingConstraint,
|
||||
topConstraint: trailingButton.topAnchor.constraint(equalTo: topAnchor),
|
||||
bottomConstraint: trailingButton.bottomAnchor.constraint(equalTo: bottomAnchor))
|
||||
|
|
@ -133,31 +132,34 @@ open class ModalHeaderView: BaseInitializableView, AppearanceConfigurable {
|
|||
switch state {
|
||||
case let .leadingButton(style):
|
||||
leadingButtonStyle = style
|
||||
leftButtonConstraints.edgeConstraints.trailingConstraint = leftTrailingToSuperviewTrailing
|
||||
leadingButtonConstraints.edgeConstraints.trailingConstraint = leftTrailingToSuperviewTrailing
|
||||
|
||||
case let .trailingButton(style):
|
||||
trailingButtonStyle = style
|
||||
rightButtonConstraints.edgeConstraints.leadingConstraint = rightLeadingToSuperviewLeadingConstraint
|
||||
trailingButtonConstraints.edgeConstraints.leadingConstraint = rightLeadingToSuperviewLeadingConstraint
|
||||
|
||||
case let .buttons(leading, trailing):
|
||||
leadingButtonStyle = leading
|
||||
trailingButtonStyle = trailing
|
||||
leftButtonConstraints.edgeConstraints.trailingConstraint = leftTrailingToRightLeadingConstraint
|
||||
rightButtonConstraints.edgeConstraints.leadingConstraint = leftTrailingToRightLeadingConstraint
|
||||
|
||||
let spacing = leading.appearance.layout.insets.add(\.right,
|
||||
to: \.left,
|
||||
of: trailing.appearance.layout.insets)
|
||||
|
||||
leftTrailingToRightLeadingConstraint.setActiveConstantOrDeactivate(constant: spacing)
|
||||
|
||||
case let .custom(view, appearance):
|
||||
configureCustomView(view, withLayout: appearance.layout)
|
||||
view.configureUIView(appearance: appearance)
|
||||
}
|
||||
|
||||
configure(buttonStyle: leadingButtonStyle, forButton: leadingButton, constraints: leftButtonConstraints)
|
||||
configure(buttonStyle: trailingButtonStyle, forButton: trailingButton, constraints: rightButtonConstraints)
|
||||
configure(buttonStyle: leadingButtonStyle, forButton: leadingButton, constraints: leadingButtonConstraints)
|
||||
configure(buttonStyle: trailingButtonStyle, forButton: trailingButton, constraints: trailingButtonConstraints)
|
||||
|
||||
if let leadingButtonStyle, let trailingButtonStyle {
|
||||
leadingButtonConstraints.edgeConstraints.trailingConstraint = leftTrailingToRightLeadingConstraint
|
||||
trailingButtonConstraints.edgeConstraints.leadingConstraint = leftTrailingToRightLeadingConstraint
|
||||
|
||||
let spacing = leadingButtonStyle.appearance.layout.insets.add(\.right,
|
||||
to: \.left,
|
||||
of: trailingButtonStyle.appearance.layout.insets)
|
||||
|
||||
leftTrailingToRightLeadingConstraint.setActiveConstantOrDeactivate(constant: spacing)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Private methods
|
||||
|
|
@ -210,7 +212,8 @@ public extension ModalHeaderView {
|
|||
|
||||
final class Appearance: BaseWrappedAppearance<DefaultWrappedLayout>, WrappedViewAppearance {
|
||||
public static var defaultAppearance: Self {
|
||||
Self()
|
||||
Self(layout: DefaultWrappedLayout(insets: .horizontal(.zero).vertical(top: .zero),
|
||||
size: .fixedHeight(44)))
|
||||
}
|
||||
|
||||
public var contentViewState: ContentViewState
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ import UIKit
|
|||
import PanModal
|
||||
|
||||
open class PassthroughDimmedView: DimmedView {
|
||||
weak var hitTestHandlerView: UIView?
|
||||
public weak var hitTestHandlerView: UIView?
|
||||
|
||||
public var isTransparent = false
|
||||
|
||||
|
|
|
|||
|
|
@ -30,21 +30,21 @@ extension UIButton {
|
|||
appearance.textAttributes?
|
||||
.configure(button: self,
|
||||
with: title(for: state),
|
||||
for: state)
|
||||
for: state)
|
||||
|
||||
if #available(iOS 15, *) {
|
||||
var config = configuration ?? .plain()
|
||||
|
||||
configureInsets(in: &config,
|
||||
contentInsets: appearance.contentLayout.contentInsets,
|
||||
titleInsets: appearance.contentLayout.titleInsets,
|
||||
imageInsets: appearance.contentLayout.imageInsets)
|
||||
contentInsets: appearance.contentLayout.contentInsets.replacingNan(with: .zero),
|
||||
titleInsets: appearance.contentLayout.titleInsets.replacingNan(with: .zero),
|
||||
imageInsets: appearance.contentLayout.imageInsets.replacingNan(with: .zero))
|
||||
|
||||
configuration = config
|
||||
} else {
|
||||
contentEdgeInsets = appearance.contentLayout.contentInsets
|
||||
titleEdgeInsets = appearance.contentLayout.titleInsets
|
||||
imageEdgeInsets = appearance.contentLayout.imageInsets
|
||||
contentEdgeInsets = appearance.contentLayout.contentInsets.replacingNan(with: .zero)
|
||||
titleEdgeInsets = appearance.contentLayout.titleInsets.replacingNan(with: .zero)
|
||||
imageEdgeInsets = appearance.contentLayout.imageInsets.replacingNan(with: .zero)
|
||||
}
|
||||
|
||||
super.configureUIView(appearance: appearance)
|
||||
|
|
@ -67,7 +67,7 @@ extension UIButton {
|
|||
currentImage
|
||||
]
|
||||
.compactMap { $0 }
|
||||
.first { !($0.size.width.isZero || $0.size.height.isZero) } != nil
|
||||
.contains { !($0.size.width.isZero || $0.size.height.isZero) }
|
||||
|
||||
if hasNonEmptyImage {
|
||||
let leadingContentInset: CGFloat
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ extension UIView {
|
|||
public var centerOffset: UIOffset
|
||||
public var insets: UIEdgeInsets
|
||||
|
||||
public init(insets: UIEdgeInsets = .zero,
|
||||
public init(insets: UIEdgeInsets = .nan,
|
||||
size: CGSize = .infinity,
|
||||
centerOffset: UIOffset = .nan) {
|
||||
|
||||
|
|
@ -73,7 +73,7 @@ extension UIView {
|
|||
open class BaseSpecedWrappedLayout: BaseWrappedLayout {
|
||||
public var spacing: CGFloat
|
||||
|
||||
public init(insets: UIEdgeInsets = .zero,
|
||||
public init(insets: UIEdgeInsets = .nan,
|
||||
size: CGSize = .infinity,
|
||||
centerOffset: UIOffset = .nan,
|
||||
spacing: CGFloat = .zero) {
|
||||
|
|
@ -98,7 +98,7 @@ extension UIView {
|
|||
public var distribution: UIStackView.Distribution
|
||||
public var alignment: UIStackView.Alignment
|
||||
|
||||
public init(insets: UIEdgeInsets = .zero,
|
||||
public init(insets: UIEdgeInsets = .nan,
|
||||
size: CGSize = .infinity,
|
||||
centerOffset: UIOffset = .nan,
|
||||
spacing: CGFloat = .zero,
|
||||
|
|
|
|||
|
|
@ -27,15 +27,13 @@ open class ContainerSeparatorTableViewCell<View: UIView>: ContainerTableViewCell
|
|||
private lazy var topSeparatorView = createTopSeparator()
|
||||
private lazy var bottomSeparatorView = createBottomSeparator()
|
||||
|
||||
private var topViewLeftConstraint: NSLayoutConstraint?
|
||||
private var topViewRightConstraint: NSLayoutConstraint?
|
||||
private var topViewTopConstraint: NSLayoutConstraint?
|
||||
private var topViewHeightConstraint: NSLayoutConstraint?
|
||||
private lazy var topSeparatorConstraints: SubviewConstraints = {
|
||||
subviewConstraints(for: topSeparatorView)
|
||||
}()
|
||||
|
||||
private var bottomViewLeftConstraint: NSLayoutConstraint?
|
||||
private var bottomViewRightConstraint: NSLayoutConstraint?
|
||||
private var bottomViewBottomConstraint: NSLayoutConstraint?
|
||||
private var bottomViewHeightConstraint: NSLayoutConstraint?
|
||||
private lazy var bottomSeparatorConstraints: SubviewConstraints = {
|
||||
subviewConstraints(for: bottomSeparatorView)
|
||||
}()
|
||||
|
||||
open func createTopSeparator() -> UIView {
|
||||
.init()
|
||||
|
|
@ -93,41 +91,17 @@ open class ContainerSeparatorTableViewCell<View: UIView>: ContainerTableViewCell
|
|||
open override func configureLayout() {
|
||||
super.configureLayout()
|
||||
|
||||
if let separatorSuperview = topSeparatorView.superview {
|
||||
topViewTopConstraint = topSeparatorView.topAnchor.constraint(equalTo: separatorSuperview.topAnchor)
|
||||
topViewRightConstraint = separatorSuperview.rightAnchor.constraint(equalTo: topSeparatorView.rightAnchor)
|
||||
topViewLeftConstraint = topSeparatorView.leftAnchor.constraint(equalTo: separatorSuperview.leftAnchor)
|
||||
for view in [topSeparatorView, bottomSeparatorView] {
|
||||
view.translatesAutoresizingMaskIntoConstraints = false
|
||||
}
|
||||
|
||||
topViewHeightConstraint = topSeparatorView.heightAnchor.constraint(equalToConstant: 1)
|
||||
|
||||
if let separatorSuperview = topSeparatorView.superview {
|
||||
bottomViewRightConstraint = separatorSuperview.rightAnchor.constraint(equalTo: bottomSeparatorView.rightAnchor)
|
||||
bottomViewLeftConstraint = bottomSeparatorView.leftAnchor.constraint(equalTo: separatorSuperview.leftAnchor)
|
||||
bottomViewBottomConstraint = bottomSeparatorView.bottomAnchor.constraint(equalTo: separatorSuperview.bottomAnchor)
|
||||
}
|
||||
|
||||
bottomViewHeightConstraint = bottomSeparatorView.heightAnchor.constraint(equalToConstant: 1)
|
||||
|
||||
NSLayoutConstraint.activate([
|
||||
topViewTopConstraint,
|
||||
topViewRightConstraint,
|
||||
topViewLeftConstraint,
|
||||
topViewHeightConstraint,
|
||||
bottomViewRightConstraint,
|
||||
bottomViewLeftConstraint,
|
||||
bottomViewBottomConstraint,
|
||||
bottomViewHeightConstraint
|
||||
].compactMap { $0 })
|
||||
}
|
||||
|
||||
open override func configureAppearance() {
|
||||
super.configureAppearance()
|
||||
|
||||
[topSeparatorView, bottomSeparatorView].forEach {
|
||||
$0.isHidden = true
|
||||
$0.backgroundColor = .black
|
||||
$0.translatesAutoresizingMaskIntoConstraints = false
|
||||
for view in [topSeparatorView, bottomSeparatorView] {
|
||||
view.isHidden = true
|
||||
view.backgroundColor = .black
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -136,20 +110,37 @@ open class ContainerSeparatorTableViewCell<View: UIView>: ContainerTableViewCell
|
|||
private func updateTopSeparator(with appearance: SeparatorAppearance) {
|
||||
topSeparatorView.configureUIView(appearance: appearance)
|
||||
|
||||
topViewHeightConstraint?.constant = appearance.layout.size.height
|
||||
|
||||
topViewTopConstraint?.constant = appearance.layout.insets.top
|
||||
topViewLeftConstraint?.constant = appearance.layout.insets.left
|
||||
topViewRightConstraint?.constant = appearance.layout.insets.right
|
||||
topSeparatorConstraints.update(from: appearance.layout)
|
||||
}
|
||||
|
||||
private func updateBottomSeparator(with appearance: SeparatorAppearance) {
|
||||
bottomSeparatorView.configureUIView(appearance: appearance)
|
||||
|
||||
bottomViewHeightConstraint?.constant = appearance.layout.size.height
|
||||
bottomSeparatorConstraints.update(from: appearance.layout)
|
||||
}
|
||||
|
||||
bottomViewBottomConstraint?.constant = appearance.layout.insets.bottom
|
||||
bottomViewLeftConstraint?.constant = appearance.layout.insets.left
|
||||
bottomViewRightConstraint?.constant = appearance.layout.insets.right
|
||||
private func subviewConstraints(for seperatorView: UIView) -> SubviewConstraints {
|
||||
let leadingConstraint = seperatorView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor)
|
||||
let trailingConstraint = seperatorView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor)
|
||||
let topConstraint = seperatorView.topAnchor.constraint(equalTo: contentView.topAnchor)
|
||||
let bottomConstraint = seperatorView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor)
|
||||
|
||||
let edgeConstraints = EdgeConstraints(leadingConstraint: leadingConstraint,
|
||||
trailingConstraint: trailingConstraint,
|
||||
topConstraint: topConstraint,
|
||||
bottomConstraint: bottomConstraint)
|
||||
|
||||
let centerXConstraint = seperatorView.centerXAnchor.constraint(equalTo: contentView.centerXAnchor)
|
||||
let centerYConstraint = seperatorView.centerYAnchor.constraint(equalTo: contentView.centerYAnchor)
|
||||
|
||||
let centerConstraints = CenterConstraints(centerXConstraint: centerXConstraint,
|
||||
centerYConstraint: centerYConstraint)
|
||||
|
||||
let sizeConstraints = SizeConstraints(widthConstraint: seperatorView.widthAnchor.constraint(equalToConstant: .zero),
|
||||
heightConstraint: seperatorView.heightAnchor.constraint(equalToConstant: .zero))
|
||||
|
||||
return SubviewConstraints(edgeConstraints: edgeConstraints,
|
||||
centerConstraints: centerConstraints,
|
||||
sizeConstraints: sizeConstraints)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -184,7 +184,8 @@ open class BaseListItemView<LeadingView: UIView,
|
|||
leadingViewLeftInset = leadingViewLayout.insets.left
|
||||
}
|
||||
|
||||
leadingToSuperviewContraint.setActiveConstantOrDeactivate(constant: leadingViewLeftInset)
|
||||
leadingToSuperviewContraint.constant = leadingViewLeftInset.isFinite ? leadingViewLeftInset : .zero
|
||||
leadingToSuperviewContraint.isActive = true
|
||||
}
|
||||
|
||||
private func update(middleViewLayout: WrappedViewLayout) {
|
||||
|
|
@ -219,6 +220,7 @@ open class BaseListItemView<LeadingView: UIView,
|
|||
trailingViewRightInset = trailingViewLayout.insets.right
|
||||
}
|
||||
|
||||
trailingToSuperviewConstraint.setActiveConstantOrDeactivate(constant: -trailingViewRightInset)
|
||||
trailingToSuperviewConstraint.constant = trailingViewRightInset.isFinite ? -trailingViewRightInset : .zero
|
||||
trailingToSuperviewConstraint.isActive = true
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,14 +47,6 @@ public struct SubviewConstraints: ConstraintsSet {
|
|||
centerConstraints.update(offset: centerOffset)
|
||||
sizeConstraints.update(from: size)
|
||||
edgeConstraints.update(from: insets)
|
||||
|
||||
for verticalConstraint in edgeConstraints.vertical {
|
||||
verticalConstraint.isActive = !centerOffset.vertical.isFinite
|
||||
}
|
||||
|
||||
for horizontalConstraint in edgeConstraints.horizontal {
|
||||
horizontalConstraint.isActive = !centerOffset.horizontal.isFinite
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - WrappedViewLayout shortcut
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ open class CollectionTableViewCell<CollectionView: UICollectionView>: ContainerT
|
|||
}
|
||||
|
||||
let cachedCollectionFrame = wrappedView.frame
|
||||
wrappedView.frame.size.width = targetSize.width - wrappedContentInsets.horizontal(onNan: .zero)
|
||||
wrappedView.frame.size.width = max(targetSize.width - wrappedContentInsets.horizontal(onNan: .zero), .zero)
|
||||
let collectionContentHeight = wrappedView.collectionViewLayout.collectionViewContentSize.height
|
||||
wrappedView.frame = cachedCollectionFrame
|
||||
|
||||
|
|
|
|||
|
|
@ -26,6 +26,10 @@ public extension UIEdgeInsets {
|
|||
|
||||
// MARK: - Factory methods
|
||||
|
||||
static var nan: Self {
|
||||
.edges(.nan)
|
||||
}
|
||||
|
||||
static func edges(_ insets: CGFloat) -> UIEdgeInsets {
|
||||
.init(top: insets, left: insets, bottom: insets, right: insets)
|
||||
}
|
||||
|
|
@ -64,14 +68,21 @@ public extension UIEdgeInsets {
|
|||
.init(top: insets, left: left, bottom: insets, right: right)
|
||||
}
|
||||
|
||||
func horizontal(left: CGFloat = .zero, right: CGFloat = .zero) -> UIEdgeInsets {
|
||||
func horizontal(left: CGFloat = .nan, right: CGFloat = .nan) -> UIEdgeInsets {
|
||||
.init(top: top, left: left, bottom: bottom, right: right)
|
||||
}
|
||||
|
||||
func vertical(top: CGFloat = .zero, bottom: CGFloat = .zero) -> UIEdgeInsets {
|
||||
func vertical(top: CGFloat = .nan, bottom: CGFloat = .nan) -> UIEdgeInsets {
|
||||
.init(top: top, left: left, bottom: bottom, right: right)
|
||||
}
|
||||
|
||||
func replacingNan(with defaultValue: CGFloat) -> Self {
|
||||
.init(top: top.isFinite ? top : defaultValue,
|
||||
left: left.isFinite ? left : defaultValue,
|
||||
bottom: bottom.isFinite ? bottom : defaultValue,
|
||||
right: right.isFinite ? right : defaultValue)
|
||||
}
|
||||
|
||||
func add(_ lhsKeyPath: KeyPath<Self, CGFloat>,
|
||||
to rhsKeyPath: KeyPath<Self, CGFloat>,
|
||||
of rhs: Self,
|
||||
|
|
|
|||
Loading…
Reference in New Issue