Scaling UITextView using contentScaleFactor proper

2019-01-23 21:51发布

I am trying to create a higher resolution image of a UIView, specifically UITextView.

This question and answer is exactly what I am trying to figure out:

stackoverflow

But, when I do the same, my text is still blurry:

self.view.transform = CGAffineTransformMakeScale(2.f, 2.f);
[myText setContentScaleFactor:2.f]; // myText is a subview of self.view object

I have also tried the same in the Apple sample project "UICatalog" to UILabel's and it is also blurry.

I can't understand why it would work for Warrior from the other question and not for me. I would have asked there - but I can't seem to leave a comment or a question there.

Any suggestions would be greatly appreciated, thanks.

3条回答
Fickle 薄情
2楼-- · 2019-01-23 22:25

Be sure to apply the contentScaleFactor to all subviews of the UITextView. I've just tested the following with a UITextView and found it to work:

- (void)applyScale:(CGFloat)scale toView:(UIView *)view {
    view.contentScaleFactor = scale;
    view.layer.contentsScale = scale;
    for (UIView *subview in view.subviews) {
        [self applyScale:scale toView:subview];
    }
}
查看更多
对你真心纯属浪费
3楼-- · 2019-01-23 22:29

UITextView has textInputView property, which "both draws the text and provides a coordinate system" (https://developer.apple.com/reference/uikit/uitextinput/1614564-textinputview)

So i'm using the following code to scale UITextView - without any font changes, without using any "CALayer" property and keeping high quality:

float screenScaleFactor = [[UIScreen mainScreen] scale];
float scale = 5.0;
textView.transform = CGAffineTransformMakeScale(scale, scale);
textView.textInputView.contentScaleFactor = screenScaleFactor * scale;

Comment the last line if you need low quality (but better performance) scaling.

Transform uses view.center as scaling center point, so adding a 'translate transform' is needed to scale around view corner.

查看更多
冷血范
4楼-- · 2019-01-23 22:31

Setting the contentScaleFactor and contentsScale is in fact the key, as @dbotha pointed out, however you have to walk the view and layer hierarchies separately in order to reach every internal CATiledLayer that actually does the text rendering. Adding the screen scale might also make sense.

So the correct implementation would be something like this:

- (void)updateForZoomScale:(CGFloat)zoomScale {
    CGFloat screenAndZoomScale = zoomScale * [UIScreen mainScreen].scale;
    // Walk the layer and view hierarchies separately. We need to reach all tiled layers.
    [self applyScale:(zoomScale * [UIScreen mainScreen].scale) toView:self.textView];
    [self applyScale:(zoomScale * [UIScreen mainScreen].scale) toLayer:self.textView.layer];
}

- (void)applyScale:(CGFloat)scale toView:(UIView *)view {
    view.contentScaleFactor = scale;
    for (UIView *subview in view.subviews) {
        [self applyScale:scale toView:subview];
    }
}

- (void)applyScale:(CGFloat)scale toLayer:(CALayer *)layer {
    layer.contentsScale = scale;
    for (CALayer *sublayer in layer.sublayers) {
        [self applyScale:scale toLayer:sublayer];
    }
}
查看更多
登录 后发表回答