ios 在 UITextView 中垂直居中文本

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12591192/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 20:22:47  来源:igfitidea点击:

Center text vertically in a UITextView

iphoneobjective-ciosxcodeuitextview

提问by Sergey Grischyov

I want to center the text verticallyinside a big UITextViewthat fills the whole screen - so that when there's little of text, say a couple of words, it is centered by height. It's not a question about centering the text (a property that can be found in IB) but about putting the text verticallyright in the middle of UITextViewifthe text is short, so there are no blank areas in the UITextView. Can this be done? Thanks in advance!

我想将文本垂直居中放置在UITextView填充整个屏幕的大文本中- 这样当文本很少时,比如说几个词,它以高度为中心。这不是关于居中文本(可以在 IB 中找到的属性)的问题,而是关于如果文本很短则将文本垂直放在中间的问题,因此. 这能做到吗?提前致谢!UITextViewUITextView

采纳答案by CSolanaM

First add an observer for the contentSizekey value of the UITextViewwhen the view is loaded:

首先为视图加载时的contentSizekey值添加一个观察者UITextView

- (void) viewDidLoad {
     [textField addObserver:self forKeyPath:@"contentSize" options:(NSKeyValueObservingOptionNew) context:NULL];
     [super viewDidLoad];
}

Then add this method to adjust the contentOffsetevery time the contentSizevalue changes:

然后添加此方法以在contentOffset每次contentSize值更改时进行调整:

-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
     UITextView *tv = object;
     CGFloat topCorrect = ([tv bounds].size.height - [tv contentSize].height * [tv zoomScale])/2.0;
     topCorrect = ( topCorrect < 0.0 ? 0.0 : topCorrect );
     tv.contentOffset = (CGPoint){.x = 0, .y = -topCorrect};
}

回答by Senseful

Because UIKit is not KVO compliant, I decided to implement this as a subclass of UITextViewwhich updates whenever the contentSizechanges.

因为UIKit 不是 KVO 兼容的,我决定将它作为一个子类来实现,UITextView它会在contentSize发生变化时更新。

It's a slightly modified version of Carlos's answerwhich sets the contentInsetinstead of the contentOffset. In addition to being compatible with iOS 9, it also seems to be less buggy on iOS 8.4.

这是Carlos 答案的略微修改版本,它设置contentInsetcontentOffset. 除了与 iOS 9 兼容之外,它在 iOS 8.4 上的问题似乎也更少。

class VerticallyCenteredTextView: UITextView {
    override var contentSize: CGSize {
        didSet {
            var topCorrection = (bounds.size.height - contentSize.height * zoomScale) / 2.0
            topCorrection = max(0, topCorrection)
            contentInset = UIEdgeInsets(top: topCorrection, left: 0, bottom: 0, right: 0)
        }
    }
}

回答by Beninho85

If you don't want to use KVO you can also manually adjust offset with exporting this code to a function like this :

如果您不想使用 KVO,您还可以通过将此代码导出到这样的函数来手动调整偏移量:

-(void)adjustContentSize:(UITextView*)tv{
    CGFloat deadSpace = ([tv bounds].size.height - [tv contentSize].height);
    CGFloat inset = MAX(0, deadSpace/2.0);
    tv.contentInset = UIEdgeInsetsMake(inset, tv.contentInset.left, inset, tv.contentInset.right);
}  

and calling it in

并调用它

-(void)textViewDidChange:(UITextView *)textView{
    [self adjustContentSize:textView];
}

and every time you edit the text in the code. Don't forget to set the controller as the delegate

每次编辑代码中的文本时。不要忘记将控制器设置为委托

Swift 3 version:

斯威夫特 3 版本:

func adjustContentSize(tv: UITextView){
    let deadSpace = tv.bounds.size.height - tv.contentSize.height
    let inset = max(0, deadSpace/2.0)
    tv.contentInset = UIEdgeInsetsMake(inset, tv.contentInset.left, inset, tv.contentInset.right)
}

func textViewDidChange(_ textView: UITextView) {
    self.adjustContentSize(tv: textView)
}

回答by s.ka

For iOS 9.0.2. we'll need to set the contentInset instead. If we KVO the contentOffset, iOS 9.0.2 sets it to 0 at the last moment, overriding the changes to contentOffset.

对于 iOS 9.0.2。我们需要改为设置 contentInset。如果我们对 contentOffset 进行 KVO,iOS 9.0.2 在最后一刻将其设置为 0,覆盖对 contentOffset 的更改。

-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    UITextView *tv = object;
    CGFloat topCorrect = ([tv bounds].size.height - [tv     contentSize].height * [tv zoomScale])/2.0;
    topCorrect = ( topCorrect < 0.0 ? 0.0 : topCorrect );
    [tv setContentInset:UIEdgeInsetsMake(topCorrect,0,0,0)];
}

- (void) viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:NO];
    [questionTextView addObserver:self forKeyPath:@"contentSize" options:(NSKeyValueObservingOptionNew) context:NULL];
}

I used 0,0, and 0 for the left,bottom and right edge insets respectively. Make sure to calculate those as well for your use case.

我分别将 0,0 和 0 用于左侧、底部和右侧边缘插入。确保也为您的用例计算这些。

回答by Rudolf Adamkovi?

Here's a UITextViewextension that centers content vertically:

这是一个UITextView垂直居中内容的扩展:

extension UITextView {

    func centerVertically() {
        let fittingSize = CGSize(width: bounds.width, height: CGFloat.max)
        let size = sizeThatFits(fittingSize)
        let topOffset = (bounds.size.height - size.height * zoomScale) / 2
        let positiveTopOffset = max(0, topOffset)
        contentOffset.y = -positiveTopOffset
    }

}

回答by KOTIOS

You can set it up directly with only constraints:

您可以仅使用约束直接设置它:

There are 3 constraints i added to align text vertically and horizontally in constraints as below :

我添加了 3 个约束来在约束中垂直和水平对齐文本,如下所示:

enter image description here

在此处输入图片说明

  1. Make height 0 and add constraints greater than
  2. Add vertically align to parent constraints
  3. Add horizontally align to parent constraints
  1. 使高度为 0 并添加大于
  2. 添加垂直对齐到父约束
  3. 添加水平对齐到父约束

enter image description here

在此处输入图片说明

回答by user1687195

I have a textview that I'm using with autolayout and with setting the lineFragmentPaddingand textContainerInsetto zero. None of the solutions above worked in my situation. However, this works for me. Tested with iOS 9

我有一个TextView,我使用与自动布局与设置lineFragmentPaddingtextContainerInset为零。上述解决方案都不适用于我的情况。但是,这对我有用。用 iOS 9 测试

@interface VerticallyCenteredTextView : UITextView
@end

@implementation VerticallyCenteredTextView

-(void)layoutSubviews{
    [self recenter];
}

-(void)recenter{
    // using self.contentSize doesn't work correctly, have to calculate content size
    CGSize contentSize = [self sizeThatFits:CGSizeMake(self.bounds.size.width, CGFLOAT_MAX)];
    CGFloat topCorrection = (self.bounds.size.height - contentSize.height * self.zoomScale) / 2.0;
    self.contentOffset = CGPointMake(0, -topCorrection);
}

@end

回答by Tai Le

I just created a custom vertically centered text view in Swift 3:

我刚刚在 Swift 3 中创建了一个自定义的垂直居中文本视图:

class VerticallyCenteredTextView: UITextView {
    override var contentSize: CGSize {
        didSet {
            var topCorrection = (bounds.size.height - contentSize.height * zoomScale) / 2.0
            topCorrection = max(0, topCorrection)
            contentInset = UIEdgeInsets(top: topCorrection, left: 0, bottom: 0, right: 0)
        }
    }
}

Ref: https://geek-is-stupid.github.io/2017-05-15-how-to-center-text-vertically-in-a-uitextview/

参考:https: //geek-is-stupid.github.io/2017-05-15-how-to-center-text-vertically-in-a-uitextview/

回答by arnaldito100

Swift 3:

斯威夫特 3:

override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()

        textField.frame = self.view.bounds

        var topCorrect : CGFloat = (self.view.frame.height / 2) - (textField.contentSize.height / 2)
        topCorrect = topCorrect < 0.0 ? 0.0 : topCorrect
        textField.contentInset = UIEdgeInsetsMake(topCorrect,0,0,0)

    }

回答by Ievgen

func alignTextVerticalInTextView(textView :UITextView) {

    let size = textView.sizeThatFits(CGSizeMake(CGRectGetWidth(textView.bounds), CGFloat(MAXFLOAT)))

    var topoffset = (textView.bounds.size.height - size.height * textView.zoomScale) / 2.0
    topoffset = topoffset < 0.0 ? 0.0 : topoffset

    textView.contentOffset = CGPointMake(0, -topoffset)
}