diff --git a/UIImageViewAligned.swift b/UIImageViewAligned.swift index 85597dd..a3f2656 100644 --- a/UIImageViewAligned.swift +++ b/UIImageViewAligned.swift @@ -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. @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 @@ -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) { @@ -244,8 +242,9 @@ 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) @@ -253,7 +252,7 @@ open class UIImageViewAligned: UIImageView { self.alignment.remove(alignment) } } - + private func getInspectableProperty(_ alignment: UIImageViewAlignmentMask) -> Bool { return self.alignment.contains(alignment) }