Summary:
In iOS 6, I centered text vertically in a UITextView by key-value-observing the text view's contentSize property (https://stackoverflow.com/a/12591299/1239263). When I upgraded to iOS 7, the latter technique worked inconsistently.
Rather than try to fix the KVO technique, I would rather use Text Kit to center text vertically in a UITextView.
I have designed a solution using Text Kit, but it breaks upon device rotation.
The UITextView is orange.
When the text view initially loads, the text is centered properly:
When the device rotates to landscape, the text is still centered properly:
However, when the device rotates back to portrait, the text is not centered properly. The text should be on one line, as it was in the first screenshot above.
For the latter screenshot, logging geometries to the console reveals that the text view's text-container width is too narrow.
Details:
@interface ViewController ()
// text view is created in storyboard; it's added to the root view and it's using auto layout
@property (weak, nonatomic) IBOutlet UITextView *textView;
@end
@implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
NSTextContainer *textContainer = self.textView.textContainer;
[textContainer setWidthTracksTextView:YES];
}
- (void)centerText
{
NSTextContainer *container = self.textView.textContainer;
NSLayoutManager *layoutManager = container.layoutManager;
CGRect textRect = [layoutManager usedRectForTextContainer:container];
UIEdgeInsets inset = UIEdgeInsetsZero;
inset.top = self.textView.bounds.size.height / 2 - textRect.size.height / 2;
inset.left = self.textView.bounds.size.width / 2 - textRect.size.width / 2;
self.textView.textContainerInset = inset;
}
- (void)viewDidLayoutSubviews
{
[self centerText];
}
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
[super willAnimateRotationToInterfaceOrientation:toInterfaceOrientation duration:duration];
[self centerText];
}
What I have tried:
I tried to manually set the container size in the centerText method. Depending upon what value I set for the container size, setting the container size does actually work in some cases. Which cases? It depends upon the number of lines of text displayed.
// fixes problem if a single line of text; clips multi-line text
container.size = CGSizeZero;
// fixes problem if multi-line text, but not if a single line of text
container.size = CGSizeMake(self.textView.bounds.size.width, FLT_MAX);
Since I'm setting widthTracksTextView to YES, I don't understand why I would need to set the text container size at all. And if I do need to set the text container width, why does the correct value seem to depend upon the number of lines displayed?