// // SegmentedReliefButton.swift // App // // Created by James Magahern on 8/14/20. // import UIKit class SegmentedReliefButton: ReliefButton { var children: [ReliefButton] = [] { willSet { children.forEach { $0.removeFromSuperview() } } didSet { children.forEach { addSubview($0) }; setNeedsLayout() } } override var isPointerInteractionEnabled: Bool { set { children.forEach { $0.isPointerInteractionEnabled = newValue } } get { children.first?.isPointerInteractionEnabled ?? false } } private let backgroundsContainerView = UIView(frame: .zero) private var childrenHighlighObservations: [NSKeyValueObservation] = [] init(children: [ReliefButton]) { super.init() self.children = children backgroundsContainerView.clipsToBounds = true backgroundsContainerView.layer.cornerRadius = self.cornerRadius + Self.borderWidth + 1.0 backgroundsContainerView.layer.cornerCurve = .continuous constrainedToSquare = false addSubview(backgroundsContainerView) } override var isHighlighted: Bool { // Does not highlight. Only children do. set {} get { false } } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } override func sizeThatFits(_ size: CGSize) -> CGSize { let ourSize = super.sizeThatFits(size) let width: CGFloat = children.reduce(0.0) { (result, button) -> CGFloat in return result + button.sizeThatFits(size).width } return CGSize(width: width + (2 * Self.borderWidth), height: ourSize.height) } override func setBackgroundInverted(_ inverted: Bool) { // no-op } override func layoutSubviews() { super.layoutSubviews() backgroundView.colors = [ .clear ] backgroundsContainerView.frame = backgroundView.frame childrenHighlighObservations.removeAll() backgroundsContainerView.subviews.forEach { $0.removeFromSuperview() } let paddedSize = CGSize( width: bounds.size.width - (Self.borderWidth * 2.0), height: bounds.size.height - (Self.borderWidth * 2.0) ) let darkMode = self.traitCollection.userInterfaceStyle == .dark var buttonXOffset = CGFloat(Self.borderWidth) for (i, child) in children.enumerated() { child.shadowView.isHidden = true child.backgroundView.isHidden = true bringSubviewToFront(child) let childSize = child.sizeThatFits(paddedSize) child.frame = CGRect( origin: CGPoint(x: buttonXOffset, y: Self.borderWidth), size: CGSize(width: childSize.width, height: paddedSize.height) ) buttonXOffset += child.frame.width // Background let backgroundView = GradientView(direction: .vertical, colors: Self.gradientColors(inverted: false, darkMode: darkMode)) backgroundView.frame = child.frame backgroundsContainerView.insertSubview(backgroundView, at: 0) childrenHighlighObservations.append(child.observe(\.isHighlighted) { [backgroundView] (button, changeEvent) in backgroundView.colors = Self.gradientColors(inverted: button.isHighlighted, darkMode: darkMode) }) // Separator if i < children.count - 1 { let separatorView = UIView(frame: CGRect( x: child.frame.maxX, y: 0, width: 1.0 / UIScreen.main.scale, height: bounds.height )) separatorView.backgroundColor = .systemFill backgroundsContainerView.addSubview(separatorView) } } } }