Reputation: 447
I'm using Swift 3 to create an iOS interface where some UIView
s containing (amongst other things) UILabel
s are scaled up and down based on where they're being positioned on the screen. My first approach was to create and populate the views at a comfortably large size (say 100x100) and then scale them as needed using CGAffineTransform(scaleX:y:)
, however I've noticed that the downscaling of the text in the labels isn't graceful at all, and the text becomes pixelated and close to unreadable at small scales. As a comparison (see example below), changing the font size directly gives much better results, however the structure within my views is somewhat complex and having to redraw everything based on some size factor would be a hassle. Is there a better and smoother way to approach this problem?
Here's an example project I've created to illustrate the problem, as well as the output in the simulator (same as on the iPhone itself), downscaled views are on the left (red) and changed font sizes are the right (green).
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
for i in 1...10 {
let f = CGFloat(1.0) / CGFloat(i)
let view1 = UIView(frame: CGRect(x: 0, y: 0, width: 150, height: 50))
view1.backgroundColor = UIColor.red
let label1 = UILabel(frame: CGRect(x: 0, y: 0, width: 150, height: 50))
label1.text = "\(100 / i)%"
label1.font = UIFont(name: "Verdana", size: 24.0)
label1.textAlignment = .right
view1.addSubview(label1)
view1.transform = CGAffineTransform(scaleX: f, y: f)
view1.center = CGPoint(x: 160 - 75.0 * f, y: CGFloat(60 * i) + 25.0 * f)
self.view.addSubview(view1)
let view2 = UIView(frame: CGRect(x: CGFloat(170), y: CGFloat(60 * i), width: 150 * f, height: 50 * f))
view2.backgroundColor = UIColor.green
let label2 = UILabel(frame: CGRect(x: 0, y: 0, width: 150 * f, height: 50 * f))
label2.text = "\(100 / i)%"
label2.font = UIFont(name: "Verdana", size: 24.0 * f)
view2.addSubview(label2)
self.view.addSubview(view2)
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Upvotes: 0
Views: 197
Reputation: 77672
This might be an answer - but not really suitable for a comment, so...
Give this a try - it creates a 3rd "column" of yellow-background views, using .adjustsFontSizeToFitWidth
. The font size will auto-adjust based on the size of the views that contain the labels.
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
for i in 1...10 {
let f = CGFloat(1.0) / CGFloat(i)
let view1 = UIView(frame: CGRect(x: 0, y: 0, width: 150, height: 50))
view1.backgroundColor = UIColor.red
let label1 = UILabel(frame: CGRect(x: 0, y: 0, width: 150, height: 50))
label1.text = "\(100 / i)%"
label1.font = UIFont(name: "Verdana", size: 24.0)
label1.textAlignment = .right
view1.addSubview(label1)
view1.transform = CGAffineTransform(scaleX: f, y: f)
view1.center = CGPoint(x: 160 - 75.0 * f, y: CGFloat(60 * i) + 25.0 * f)
self.view.addSubview(view1)
let view2 = UIView(frame: CGRect(x: CGFloat(170), y: CGFloat(60 * i), width: 150 * f, height: 50 * f))
view2.backgroundColor = UIColor.green
let label2 = UILabel(frame: CGRect(x: 0, y: 0, width: 150 * f, height: 50 * f))
label2.text = "\(100 / i)%"
label2.font = UIFont(name: "Verdana", size: 24.0 * f)
view2.addSubview(label2)
self.view.addSubview(view2)
let view3 = UIView(frame: CGRect(x: CGFloat(270), y: CGFloat(60 * i), width: 150 * f, height: 50 * f))
view3.backgroundColor = UIColor.yellow
let label3 = UILabel(frame: view3.bounds)
label3.text = "\(100 / i)%"
label3.font = UIFont(name: "Verdana", size: 24.0)
label3.adjustsFontSizeToFitWidth = true
label3.minimumScaleFactor = 0.05
label3.numberOfLines = 0
// we want the label to resize with the view, if the view frame changes
label3.autoresizingMask = [.flexibleWidth, .flexibleHeight]
view3.autoresizesSubviews = true
view3.addSubview(label3)
self.view.addSubview(view3)
}
}
Upvotes: 1