Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IOS-10712: Added left image #409

Merged
merged 3 commits into from
Nov 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import UIKit

class UICatalogButtonsViewController: UITableViewController {
private enum Constants {
static let exampleImage = UIImage(named: "Alerts")!
static let states: [Button.State] = [.normal, .selected, .disabled, .loading]
static var styles: [Style] {
[
Expand All @@ -34,7 +35,14 @@ class UICatalogButtonsViewController: UITableViewController {

// Chevron

Style(buttonStyle: .link, title: "Chevron", isInverse: false, isSmall: false, rightImage: .chevron)
Style(buttonStyle: .link, title: "Chevron", isInverse: false, isSmall: false, rightImage: .chevron),

// Images

Style(buttonStyle: .primary, title: "Left image", isInverse: false, isSmall: false, leftImage: .custom(image: exampleImage), rightImage: nil),
Style(buttonStyle: .primary, title: "Right image", isInverse: false, isSmall: false, leftImage: nil, rightImage: .custom(image: exampleImage)),
Style(buttonStyle: .primary, title: "Both images", isInverse: false, isSmall: false, leftImage: .custom(image: exampleImage), rightImage: .custom(image: exampleImage)),
Style(buttonStyle: .primary, title: "Left image and chevron", isInverse: false, isSmall: false, leftImage: .custom(image: exampleImage), rightImage: .chevron)
]
}

Expand Down Expand Up @@ -67,17 +75,20 @@ class UICatalogButtonsViewController: UITableViewController {
let title: String
let isInverse: Bool
let isSmall: Bool
let leftImage: Button.LeftImage?
let rightImage: Button.RightImage?

init(buttonStyle: Button.Style,
title: String,
isInverse: Bool,
isSmall: Bool,
leftImage: Button.LeftImage? = nil,
rightImage: Button.RightImage? = nil) {
self.buttonStyle = buttonStyle
self.title = title
self.isInverse = isInverse
self.isSmall = isSmall
self.leftImage = leftImage
self.rightImage = rightImage
}
}
Expand Down Expand Up @@ -128,7 +139,14 @@ class UICatalogButtonsViewController: UITableViewController {

let cell = UITableViewCell()

let button = state.makeButton(style: style.buttonStyle, title: "Title", loadingTitle: "Loading Title", isSmall: style.isSmall, rightImage: style.rightImage)
let button = state.makeButton(
style: style.buttonStyle,
title: "Title",
loadingTitle: "Loading Title",
isSmall: style.isSmall,
leftImage: style.leftImage,
rightImage: style.rightImage
)
cell.configure(with: button)
cell.contentView.backgroundColor = style.isInverse ? .navigationBarBackground : .backgroundContainer

Expand Down Expand Up @@ -172,8 +190,15 @@ private extension UITableViewCell {
}

private class LoadSimulationButton: Button {
override init(style: Button.Style = .primary, title: String, rightImage: RightImage? = nil, loadingTitle: String? = nil, isSmall: Bool = false) {
super.init(style: style, title: title, rightImage: rightImage, loadingTitle: loadingTitle, isSmall: isSmall)
override init(
style: Button.Style = .primary,
title: String,
leftImage: LeftImage? = nil,
rightImage: RightImage? = nil,
loadingTitle: String? = nil,
isSmall: Bool = false
) {
super.init(style: style, title: title, leftImage: leftImage, rightImage: rightImage, loadingTitle: loadingTitle, isSmall: isSmall)
addTarget(self, action: #selector(simulateLoad), for: .touchUpInside)
}

Expand All @@ -191,23 +216,58 @@ private class LoadSimulationButton: Button {
}

private extension Button.State {
func makeButton(style: Button.Style, title _: String, loadingTitle _: String, isSmall: Bool, rightImage: Button.RightImage?) -> Button {
func makeButton(
style: Button.Style,
title _: String,
loadingTitle _: String,
isSmall: Bool,
leftImage: Button.LeftImage?,
rightImage: Button.RightImage?
) -> Button {
let button: Button

switch self {
case .selected:
button = Button(style: style, title: "Title", rightImage: rightImage, loadingTitle: "Loading Title", isSmall: isSmall)
button = Button(
style: style,
title: "Title",
leftImage: leftImage,
rightImage: rightImage,
loadingTitle: "Loading Title",
isSmall: isSmall
)
button.title = "Selected"
button.isSelected = true
button.isUserInteractionEnabled = false
case .disabled:
button = Button(style: style, title: "Title", rightImage: rightImage, loadingTitle: "Loading Title", isSmall: isSmall)
button = Button(
style: style,
title: "Title",
leftImage: leftImage,
rightImage: rightImage,
loadingTitle: "Loading Title",
isSmall: isSmall
)
button.title = "Disabled"
button.isEnabled = false
case .loading:
button = LoadSimulationButton(style: style, title: "Loading", rightImage: rightImage, loadingTitle: "Loading Title", isSmall: isSmall)
button = LoadSimulationButton(
style: style,
title: "Loading",
leftImage: leftImage,
rightImage: rightImage,
loadingTitle: "Loading Title",
isSmall: isSmall
)
case .normal:
button = Button(style: style, title: "Title", rightImage: rightImage, loadingTitle: "Loading Title", isSmall: isSmall)
button = Button(
style: style,
title: "Title",
leftImage: leftImage,
rightImage: rightImage,
loadingTitle: "Loading Title",
isSmall: isSmall
)
button.title = "Normal"
default:
fatalError("Unknown state")
Expand Down
35 changes: 34 additions & 1 deletion Sources/Mistica/Components/Button/Button.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,17 +27,20 @@ open class Button: UIControl {
public let insets: UIEdgeInsets
public let minimumWidth: CGFloat
public let font: UIFont
public let leftImageHeight: CGFloat?
public let rightImageHeight: CGFloat?

public init(
insets: UIEdgeInsets,
minimumWidth: CGFloat,
font: UIFont,
leftImageHeight: CGFloat? = nil,
rightImageHeight: CGFloat? = nil
) {
self.insets = insets
self.minimumWidth = minimumWidth
self.font = font
self.leftImageHeight = leftImageHeight
self.rightImageHeight = rightImageHeight
}
}
Expand All @@ -63,6 +66,22 @@ open class Button: UIControl {
}
}

public enum LeftImage {
case custom(image: UIImage)

var image: UIImage {
switch self {
case .custom(let image): return image.withRenderingMode(.alwaysTemplate)
}
}

var space: CGFloat {
switch self {
case .custom: return 8
}
}
}

public enum RightImage {
case chevron
case custom(image: UIImage)
Expand Down Expand Up @@ -108,6 +127,11 @@ open class Button: UIControl {
set { container.loadingTitle = newValue }
}

public var leftImage: LeftImage? {
get { container.leftImage }
set { container.leftImage = newValue }
}

public var rightImage: RightImage? {
get { container.rightImage }
set { container.rightImage = newValue }
Expand All @@ -128,13 +152,21 @@ open class Button: UIControl {
self.init(title: "")
}

public init(style: Style = .primary, title: String, rightImage: RightImage? = nil, loadingTitle: String? = nil, isSmall: Bool = false) {
public init(
style: Style = .primary,
title: String,
leftImage: LeftImage? = nil,
rightImage: RightImage? = nil,
loadingTitle: String? = nil,
isSmall: Bool = false
) {
self.style = style
self.isSmall = isSmall

super.init(frame: .zero)

self.title = title
self.leftImage = leftImage
self.rightImage = rightImage
self.loadingTitle = loadingTitle
commonInit()
Expand Down Expand Up @@ -268,6 +300,7 @@ private extension Button {
updateInsets()
container.minimumWidth = style.minimumWidth(isSmall: isSmall)
container.font = style.font(isSmall: isSmall)
container.leftImageHeight = style.leftImageHeight(isSmall: isSmall)
container.rightImageHeight = style.rightImageHeight(isSmall: isSmall)
}

Expand Down
28 changes: 28 additions & 0 deletions Sources/Mistica/Components/Button/ButtonContentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ class ButtonContentView: UIView {

private lazy var titleStackView: UIStackView = {
let stackView = UIStackView(arrangedSubviews: [
leftImageView,
titleLabel,
rightImageView
])
Expand All @@ -33,6 +34,14 @@ class ButtonContentView: UIView {
return titleLabel
}()

private let leftImageView: UIImageView = {
let imageView = UIImageView()
imageView.adjustsImageSizeForAccessibilityContentSizeCategory = true
imageView.contentMode = .scaleAspectFit
imageView.isHidden = true
return imageView
}()

private let rightImageView: UIImageView = {
let imageView = UIImageView()
imageView.adjustsImageSizeForAccessibilityContentSizeCategory = true
Expand All @@ -41,6 +50,7 @@ class ButtonContentView: UIView {
return imageView
}()

private lazy var leftImageHeightConstraint: NSLayoutConstraint = leftImageView.heightAnchor.constraint(equalToConstant: 1)
private lazy var rightImageHeightConstraint: NSLayoutConstraint = rightImageView.heightAnchor.constraint(equalToConstant: 1)

private lazy var loadingIndicator: UIActivityIndicatorView = {
Expand Down Expand Up @@ -85,11 +95,21 @@ class ButtonContentView: UIView {
set {
loadingIndicator.color = newValue
titleLabel.textColor = newValue
leftImageView.tintColor = newValue
rightImageView.tintColor = newValue
loadingTitleLabel.textColor = newValue
}
}

var leftImage: Button.LeftImage? {
didSet {
leftImageView.isHidden = leftImage == nil
guard let leftImage else { return }
titleStackView.setCustomSpacing(leftImage.space, after: leftImageView)
leftImageView.image = leftImage.image
}
}

var rightImage: Button.RightImage? {
didSet {
rightImageView.isHidden = rightImage == nil
Expand All @@ -99,6 +119,11 @@ class ButtonContentView: UIView {
}
}

var leftImageHeight: CGFloat {
get { leftImageHeightConstraint.constant }
set { leftImageHeightConstraint.constant = newValue }
}

var rightImageHeight: CGFloat {
get { rightImageHeightConstraint.constant }
set { rightImageHeightConstraint.constant = newValue }
Expand Down Expand Up @@ -138,6 +163,9 @@ class ButtonContentView: UIView {
addSubview(constrainedToLayoutMarginsGuideOf: titleContentStackView)
addSubview(constrainedToLayoutMarginsGuideOf: loadingStackView)

leftImageHeightConstraint.isActive = true
leftImageHeightConstraint.priority = .defaultLow

rightImageHeightConstraint.isActive = true
rightImageHeightConstraint.priority = .defaultLow
}
Expand Down
8 changes: 8 additions & 0 deletions Sources/Mistica/Components/Button/ButtonStyle+Toolkit.swift
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,14 @@ public extension Button.Style {
return isSmall ? Button.Style.smallMinimumWidth : Button.Style.regularMinimumWidth
}

func leftImageHeight(isSmall: Bool) -> CGFloat {
if let leftImageHeight = overriddenSizes?.leftImageHeight {
return leftImageHeight
}

return isSmall ? Button.Style.ImageHeight.small : Button.Style.ImageHeight.regular
}

func rightImageHeight(isSmall: Bool) -> CGFloat {
if let rightImageHeight = overriddenSizes?.rightImageHeight {
return rightImageHeight
Expand Down
Loading
Loading