简体   繁体   English

如何使用文本工具包(iOS 7)在UITextView中垂直居中文本

[英]How to Center Text Vertically in a UITextView using Text Kit (iOS 7)

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 ). 在iOS 6中,我通过键值观察文本视图的contentSize属性( https://stackoverflow.com/a/12591299/1239263 ),在UITextView中垂直居中。 When I upgraded to iOS 7, the latter technique worked inconsistently. 当我升级到iOS 7时,后一种技术工作不一致。

Rather than try to fix the KVO technique, I would rather use Text Kit to center text vertically in a UITextView. 我宁愿使用Text Kit在UITextView中垂直居中文本,而不是尝试修复KVO技术。

I have designed a solution using Text Kit, but it breaks upon device rotation. 我使用Text Kit设计了一个解决方案,但它会在设备轮换时中断。

The UITextView is orange. UITextView是橙色的。

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. 我试图在centerText方法中手动设置容器大小。 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. 由于我将widthTracksTextView设置为YES,我不明白为什么我需要设置文本容器大小。 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? 如果我确实需要设置文本容器宽度,为什么正确的值似乎取决于显示的行数?

I think I found both explanation and solution. 我想我找到了解释和解决方案。 The container itself has some problems with fragment of lines. 容器本身存在线段碎片的一些问题。 This is what I saw in the package. 这就是我在包装中看到的。

Returns the bounds of a line fragment rect inside the receiver for proposedRect. 返回receiverRect接收器内的行片段rect的边界。 This is the intersection of proposedRect and the receiver's bounding rect defined by -size property. 这是proposedRect和-size属性定义的接收者的边界矩形的交集。 The regions defined by -exclusionPaths property are excluded from the return value. -exclusionPaths属性定义的区域将从返回值中排除。 charIndex is the character location inside the text storage for the line fragment being processed. charIndex是正在处理的行片段的文本存储内的字符位置。 It is possible that proposedRect can be divided into multiple line fragments due to exclusion paths. 由于排除路径,proposedRect可能被划分为多个行片段。

When you use rotation of screen, the exclusionPaths are excluded. 使用屏幕旋转时,将排除exclusionPaths。 So the text cannot save the orientation value you want. 因此文本无法保存您想要的方向值。 That is why when you define the CGRect, it solved the problem somehow. 这就是为什么当你定义CGRect时,它以某种方式解决了这个问题。 So the method you should use is: 所以你应该使用的方法是:

- (CGRect)lineFragmentRectForProposedRect:(CGRect)proposedRect atIndex:(NSUInteger)characterIndex writingDirection:(NSWritingDirection)baseWritingDirection remainingRect:(CGRect *)remainingRect;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM