Hav you have ever put a UIView in a StackView and wondered why "Fill Proportionally" wasn't working when you set the UIView's "Intrinsic Size"?
It's because the UIView doesn't let the intrinsic value be set, and therefore it can't be read.
So, I am thinking, there must be a way to add a property to the UIView via a subclass that will get the job done.
The approach is to use @IBInspectable.
Here is the source:
//
// UIViewExtended.swift
//
// Created by Geoffrey Slinker on 5/28/22.
// Copyright © 2022 Geoffrey Slinker. All rights reserved.
//
import Foundation
import UIKit
class UIViewExtended : UIView {
enum Keys: String {
case proportionalSize = "ProportionalSize"
}
var proportionalSize : CGSize
override init(frame: CGRect) {
proportionalSize = CGSize(width:1.0, height:1.0)
super.init(frame:frame)
}
required init?(coder aDecoder: NSCoder) {
let tempSize : CGSize? = aDecoder.decodeCGSize(forKey: Keys.proportionalSize.rawValue) as? CGSize
if tempSize != nil {
proportionalSize = tempSize!
}
else {
proportionalSize = CGSize(width:1.0, height:1.0)
}
super.init(coder: aDecoder)
}
override func encode(with coder: NSCoder) {
coder.encode(self.proportionalSize, forKey: Keys.proportionalSize.rawValue)
super.encode(with: coder)
}
@IBInspectable var intrinsicSize: CGSize {
get {
return proportionalSize
}
set {
proportionalSize = newValue
}
}
override open var intrinsicContentSize : CGSize {
get {
return proportionalSize
}
}
}
Just set the intrinsic size in IB (Interface Builder). If you want to have the simulated view in IB look the same, keep the custom intrinsic size the same as the intrinsic size placeholder values. Yes, you have to manually keep the values the same, but at least you can do it all in IB.
Set the values here:
func testUIViewExtended() throws {
let view : UIViewExtended = UIViewExtended.init(frame: CGRect(x: 0,y: 0, width: 100, height: 50))
view.intrinsicSize = CGSize(width: 5,height: 5)
//Look at the xml in the debugger
let archiver = NSKeyedArchiver(requiringSecureCoding: false)
archiver.outputFormat = .xml
archiver.encodeRootObject(view)
let someData = archiver.encodedData
let stringData = String(decoding: someData, as: UTF8.self)
let codedData = try! NSKeyedArchiver.archivedData(withRootObject: view,
requiringSecureCoding: false)
let result = try! NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(codedData) as?
UIViewExtended
XCTAssert(result?.frame.width == 100)
XCTAssert(result?.frame.height == 50)
XCTAssert(result?.intrinsicSize.width == 5)
XCTAssert(result?.intrinsicSize.height == 5)
}
See also:
No comments:
Post a Comment