Skip to content
Open
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
123 changes: 61 additions & 62 deletions UIImageViewAligned.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import UIKit
public struct UIImageViewAlignmentMask: OptionSet {
public let rawValue: Int
public init(rawValue: Int) { self.rawValue = rawValue }

/// The option to align the content to the center.
public static let center = UIImageViewAlignmentMask(rawValue: 0)
/// The option to align the content to the left.
Expand All @@ -32,11 +32,11 @@ public struct UIImageViewAlignmentMask: OptionSet {
}

@IBDesignable
open class UIImageViewAligned: UIImageView {
open class UIImageViewAligned: UIView {

/**
The technique to use for aligning the image.

Changes to this property can be animated.
*/
open var alignment: UIImageViewAlignmentMask = .center {
Expand All @@ -45,30 +45,30 @@ open class UIImageViewAligned: UIImageView {
updateLayout()
}
}
open override var image: UIImage? {

open var image: UIImage? {
set {
realImageView?.image = newValue
imageView?.image = newValue
setNeedsLayout()
}
get {
return realImageView?.image
return imageView?.image
}
}
open override var highlightedImage: UIImage? {

open var highlightedImage: UIImage? {
set {
realImageView?.highlightedImage = newValue
imageView?.highlightedImage = newValue
setNeedsLayout()
}
get {
return realImageView?.highlightedImage
return imageView?.highlightedImage
}
}

/**
The option to align the content to the top.

It is available in Interface Builder and should not be set programmatically. Use `alignment` property if you want to set alignment outside Interface Builder.
*/
@IBInspectable open var alignTop: Bool {
Expand All @@ -79,10 +79,10 @@ open class UIImageViewAligned: UIImageView {
return getInspectableProperty(.top)
}
}

/**
The option to align the content to the left.

It is available in Interface Builder and should not be set programmatically. Use `alignment` property if you want to set alignment outside Interface Builder.
*/
@IBInspectable open var alignLeft: Bool {
Expand All @@ -93,10 +93,10 @@ open class UIImageViewAligned: UIImageView {
return getInspectableProperty(.left)
}
}

/**
The option to align the content to the right.

It is available in Interface Builder and should not be set programmatically. Use `alignment` property if you want to set alignment outside Interface Builder.
*/
@IBInspectable open var alignRight: Bool {
Expand All @@ -107,10 +107,10 @@ open class UIImageViewAligned: UIImageView {
return getInspectableProperty(.right)
}
}

/**
The option to align the content to the bottom.

It is available in Interface Builder and should not be set programmatically. Use `alignment` property if you want to set alignment outside Interface Builder.
*/
@IBInspectable open var alignBottom: Bool {
Expand All @@ -121,78 +121,70 @@ open class UIImageViewAligned: UIImageView {
return getInspectableProperty(.bottom)
}
}

open override var isHighlighted: Bool {
set {
super.isHighlighted = newValue
layer.contents = nil
}
get {
return super.isHighlighted
}
}


open var isHighlighted: Bool = false

/**
The inner image view.

It should be used only when necessary.
Accessible to keep compatibility with the original `UIImageViewAligned`.
*/
public private(set) var realImageView: UIImageView?
public private(set) var imageView: UIImageView?

private var realContentSize: CGSize {
var size = bounds.size

guard let image = image else { return size }

let scaleX = size.width / image.size.width
let scaleY = size.height / image.size.height

switch contentMode {
case .scaleAspectFill:
let scale = max(scaleX, scaleY)
size = CGSize(width: image.size.width * scale, height: image.size.height * scale)

case .scaleAspectFit:
let scale = min(scaleX, scaleY)
size = CGSize(width: image.size.width * scale, height: image.size.height * scale)

case .scaleToFill:
size = CGSize(width: image.size.width * scaleX, height: image.size.height * scaleY)

default:
size = image.size
}

return size
}

public override init(frame: CGRect) {
super.init(frame: frame)
setup()
}
public override init(image: UIImage?) {
super.init(image: image)

public init(image: UIImage?) {
super.init(frame: .zero)
setup(image: image)
}
public override init(image: UIImage?, highlightedImage: UIImage?) {
super.init(image: image, highlightedImage: highlightedImage)

public init(image: UIImage?, highlightedImage: UIImage?) {
super.init(frame: .zero)
setup(image: image, highlightedImage: highlightedImage)
}

public required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setup()
}

open override func layoutSubviews() {
super.layoutSubviews()
layoutIfNeeded()
updateLayout()
}

open override func didMoveToSuperview() {
super.didMoveToSuperview()
layer.contents = nil
Expand All @@ -207,30 +199,36 @@ open class UIImageViewAligned: UIImageView {
realImageView?.image = currentImage
}
}

private func setup(image: UIImage? = nil, highlightedImage: UIImage? = nil) {
realImageView = UIImageView(image: image ?? super.image, highlightedImage: highlightedImage ?? super.highlightedImage)
realImageView?.frame = bounds
realImageView?.autoresizingMask = [.flexibleWidth, .flexibleHeight]
realImageView?.contentMode = contentMode
addSubview(realImageView!)
imageView = UIImageView(image: image , highlightedImage: highlightedImage)
imageView?.frame = bounds
imageView?.autoresizingMask = [.flexibleWidth, .flexibleHeight]
imageView?.contentMode = contentMode
let newImageView = UIImageView(image: image , highlightedImage: highlightedImage)
newImageView.frame = bounds
newImageView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
newImageView.contentMode = contentMode
addSubview(newImageView)
imageView = newImageView
}

private func updateLayout() {
let realSize = realContentSize

var realFrame = CGRect(
origin: CGPoint(
x: (bounds.size.width - realSize.width) / 2.0,
y: (bounds.size.height - realSize.height) / 2.0),
size: realSize
)

if alignment.contains(.left) {
realFrame.origin.x = 0.0
} else if alignment.contains(.right) {
realFrame.origin.x = bounds.maxX - realFrame.size.width
}

if alignment.contains(.top) {
realFrame.origin.y = 0.0
} else if alignment.contains(.bottom) {
Expand All @@ -244,16 +242,17 @@ open class UIImageViewAligned: UIImageView {
if #available(tvOS 11, iOS 11, *) {
super.image = UIImage()
}

}

private func setInspectableProperty(_ newValue: Bool, alignment: UIImageViewAlignmentMask) {
if newValue {
self.alignment.insert(alignment)
} else {
self.alignment.remove(alignment)
}
}

private func getInspectableProperty(_ alignment: UIImageViewAlignmentMask) -> Bool {
return self.alignment.contains(alignment)
}
Expand Down