I have a number of text contols in a scrollView that can be zoomed. In order to redraw the controls at a higher resolution to avoid blurry text, I set each view's contentScaleFactor in the view hierarchy as explained here. Everything works fine for labels and textfields but textViews do not redraw at the higher scale factor. I noticed that the only other subview for textViews that may make a difference if set is a private class UIWebDocumentView which implements content like UIWebView ( ie WebKit) but the new scale factor is ignored if set at either level ( UITextView or UIWebDocumentView ).
Any ideas how to reset the scale factor ( resolution ) for TextViews specifically ?
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. You also need to account for the screen scale.
The 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];
}
}
You can than call this when the zoom scale changes (part of UIScrollViewDelegate
):
- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(CGFloat)scale {
[self updateForZoomScale:scale];
}
I filed an enhancement request here: rdar://21443666 (http://www.openradar.me/21443666). There's also a sample project with the workaround attached.
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];
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With