Path: blob/main/SignalUI/UIKitExtensions/UIStackView+SignalUI.swift
1 views
//
// Copyright 2023 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
//
import UIKit
public extension NSDirectionalEdgeInsets {
static var buttonContainerLayoutMargins: NSDirectionalEdgeInsets {
return .init(top: 0, leading: 12, bottom: 16, trailing: 12)
}
}
public extension UIStackView {
func addArrangedSubviews(_ subviews: [UIView]) {
for subview in subviews {
addArrangedSubview(subview)
}
}
func removeArrangedSubviewsAfter(_ subview: UIView) {
guard let subviewIndex = arrangedSubviews.firstIndex(of: subview) else { return }
let viewsToRemove = arrangedSubviews.suffix(from: subviewIndex.advanced(by: 1))
for view in viewsToRemove {
removeArrangedSubview(view)
}
}
func addHairline(with color: UIColor) {
insertHairline(with: color, at: arrangedSubviews.count)
}
func insertHairline(with color: UIColor, at index: Int) {
let hairlineView = UIView()
hairlineView.backgroundColor = color
hairlineView.autoSetDimension(.height, toSize: 1)
insertArrangedSubview(hairlineView, at: index)
}
func addBackgroundView(_ backgroundView: UIView) {
addSubview(backgroundView)
sendSubviewToBack(backgroundView)
backgroundView.autoPinEdgesToSuperviewEdges()
}
@discardableResult
func addBackgroundView(withBackgroundColor backgroundColor: UIColor, cornerRadius: CGFloat = 0) -> UIView {
let backgroundView = UIView(frame: bounds)
backgroundView.backgroundColor = backgroundColor
backgroundView.layer.cornerRadius = cornerRadius
self.addBackgroundView(backgroundView)
return backgroundView
}
/// Adds a `UIVisualEffectView` with a `UIBlurEffect` as a background to the view.
/// - Parameters:
/// - blur: The blur effect style to use.
/// - accessibilityFallbackColor: An optional fallback color when the
/// system "Reduce Transparency" accessibility feature is enabled. If this
/// is not set, the system automatically calculates a color to use.
/// - cornerRadius: The corner radius the background view should have.
/// - Returns: The background subview which has been added and pinned to the superview.
@discardableResult
func addBackgroundBlurView(
blur: UIBlurEffect.Style,
accessibilityFallbackColor: UIColor? = nil,
cornerRadius: CGFloat = 0,
) -> UIView {
if
UIAccessibility.isReduceTransparencyEnabled,
let accessibilityFallbackColor
{
return self.addBackgroundView(
withBackgroundColor: accessibilityFallbackColor,
cornerRadius: cornerRadius,
)
} else {
let blurEffectView = UIVisualEffectView(effect: UIBlurEffect(style: blur))
self.addBackgroundView(blurEffectView)
return blurEffectView
}
}
@discardableResult
func addBorderView(withColor color: UIColor, strokeWidth: CGFloat, cornerRadius: CGFloat = 0) -> UIView {
let borderView = UIView(frame: bounds)
borderView.isUserInteractionEnabled = false
borderView.backgroundColor = .clear
borderView.isOpaque = false
borderView.layer.borderColor = color.cgColor
borderView.layer.borderWidth = strokeWidth
borderView.layer.cornerRadius = cornerRadius
addSubview(borderView)
borderView.autoPinEdgesToSuperviewEdges()
return borderView
}
@discardableResult
func addPillBackgroundView(backgroundColor: UIColor) -> UIView {
let backgroundView = OWSLayerView.pillView()
backgroundView.backgroundColor = backgroundColor
self.addBackgroundView(backgroundView)
return backgroundView
}
class func verticalButtonStack(buttons: [UIButton], isFullWidthButtons: Bool = true) -> UIStackView {
let stackView = UIStackView(arrangedSubviews: buttons)
stackView.axis = .vertical
stackView.spacing = 12
stackView.alignment = isFullWidthButtons ? .fill : .center
stackView.isLayoutMarginsRelativeArrangement = true
stackView.directionalLayoutMargins = .buttonContainerLayoutMargins
return stackView
}
}
public extension UIView {
/// A Boolean value that determines whether the view is hidden while working
/// around a UIStackView bug where hidden subviews sometimes re-appear.
var isHiddenInStackView: Bool {
get { isHidden }
set {
// Setting isHidden to true when already hidden can cause layout issues
if isHidden != newValue {
isHidden = newValue
}
alpha = newValue ? 0 : 1
}
}
}