5

When I add a UILabel with text to a UIView and then scale the UIView, the contents is displayed with pixelation. The greater the scale factor, the greater the pixelation.

I understand using a CATextLayer might be able to assist and could display the scaled UIView and UILabel text without pixelation but I don't know how to implement it.

This is how I create a triangle and scale it with no pixelation. It scales with perfect sharp edges.

How can I ensure the same when scaling a UILabel ?

func drawTriangle() {
    let path = UIBezierPath()
    path.moveToPoint(CGPoint(x: 0, y: 100))
    path.addLineToPoint(CGPoint(x: 100, y: 100))
    path.addLineToPoint(CGPoint(x: 50, y: 0))
    path.closePath()

    let shape = CAShapeLayer()
    shape.path = path.CGPath
    shape.fillColor = UIColor.blackColor().CGColor

    viewTriangle.layer.insertSublayer(shape, atIndex: 0)
}

func scaleTriangle() {
    viewTriangle.transform = CGAffineTransformMakeScale(5, 5)
}

Question:

In Swift code, how do I convert the below to use a CATextLayer so that it scales with no pixelation?


Problem code:

func drawLetter() { // pixelated when scaled ?
    let labelLetter = UILabel(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
    labelLetter.text = "A"
    labelLetter.backgroundColor = UIColor.clearColor()
    labelLetter.textColor = UIColor.blackColor()
    labelLetter.font = UIFont(name: labelLetter.font.fontName, size: 144)
    labelLetter.textAlignment = .Center
    viewLetter.addSubview(labelLetter)
    }
}

func scaleView() {
    let scaleValue: CGFloat = 5
    self.viewLetter.transform = CGAffineTransformMakeScale(scaleValue, scaleValue)
}

Image:

enter image description here

user4806509
  • 2,925
  • 5
  • 37
  • 72
  • 1
    is there a reason you are using scale instead of actually changing the height/width of the view to make it bigger? you could do that to resolve the pixelation issue – Rishabh Oct 25 '17 at 06:13
  • HI, @Rishabh . I guess I use a transform scale method because it animates well with a `UIView.animateWithDuration` method. So I’m really looking for a transform scale method, but I’m happy to look at other suggestions. I’ve just updated the question with more details. – user4806509 Oct 26 '17 at 08:53
  • @user4806509 Did the below answer not work? – Mars Oct 28 '17 at 04:44
  • Thanks, @Mars Unfortunately adding `.contentScaleFactor` does not eliminate the pixellation. – user4806509 Oct 29 '17 at 23:15
  • Perhaps you could make your label font 5x larger and set initial scale to 0.2 and then when you want to zoom it you would scale it to 1.0 scale. – Leszek Szary Nov 13 '21 at 09:40

2 Answers2

1

I understand using a CATextLayer uses paths for drawing and will display the scaled UIView and UILabel text without pixelation.

You understand wrong. A CATextLayer draws text and scales its text. This is an either-or thing: use CATextLayer or a UILabel.

It's easy to get more detail in a scaled view: that is what a view's contentScaleFactor is for. Simply increase it, taking into account the existing scale due to the resolution of the screen, to match your scale transform.

matt
  • 515,959
  • 87
  • 875
  • 1,141
  • Thanks, but I'm not understanding @matt . Can you show in code how to use `contentScaleFactor` to scale `viewLetter` above? Also, is `contentScaleFactor` able to be animated when using a `UIView.animateWithDuration(`? – user4806509 Oct 10 '17 at 02:45
  • 2
    Hi, @Matt , I asked a very specific Swift question and you gave an incomplete answer with vague reference to contentScaleFactor which you wouldn’t elaborate on. You followed up with a link to a very broad topic, not an answer, in an Objective C book that links to a paid book you author and are promoting, seen across many other answers you have posted on StackOverflow, see https://www.google.com/search?q=%22apeth.com%2FiOSBook%22+site%3Astackoverflow.com. Forgive me, but this is inappropriate. Either try help with a focused answer to the question or refrain from spamming StackOverflow please. – user4806509 Oct 10 '17 at 05:37
1

This scales up the view 5x and sets the content's scale as well

func scaleView() {
    let scaleValue: CGFloat = 5
    self.viewLetter.transform = CGAffineTransformMakeScale(scaleValue, scaleValue)
    self.labelLetter.contentScaleFactor = scaleValue * x //scaleValue * native content scale  (2 on iPhone 8 and 3 on iPhone 8 plus)
}
Mars
  • 2,505
  • 17
  • 26
  • Thanks, @Mars Unfortunately adding `.contentScaleFactor` does not eliminate the pixellation. – user4806509 Oct 29 '17 at 21:02
  • It worked for me... but I modified the code a little bit. Try plugging in higher values for x – Mars Oct 30 '17 at 04:07
  • 1
    X is not arbitrary; its the native content scale times the zoom. In the above its 2*5 or 10 on iPhone 8 and 3*5 or 15 on iPhone 8 plus. – Josh Homann Nov 04 '17 at 07:41
  • Thanks, edited that in. I personally tested it with an arbitrary number and had no issues with overscaling, but good to know that it can be determined – Mars Nov 05 '17 at 14:42
  • Thanks, @Mars. So you aren't getting pixellated output but instead perfectly precise letter "A" at x5 x10 x15 etc ? – user4806509 Nov 11 '17 at 02:14
  • @user4806509 I believe so. When I tested it, I wasn't using English characters/font, but it should still be the same. Is it still not working for you? – Mars Nov 12 '17 at 12:38