Ik wil de tekst verticaalcentreren in een grote UITextView
die het hele scherm vult – zodat wanneer er weinig tekst is, zeg maar een paar woorden, het is gecentreerd op hoogte.
Het gaat niet om het centreren van de tekst (een eigenschap die in IB te vinden is) maar om het verticaalin het midden van UITextView
ifplaatsen em>de tekst is kort, dus er zijn geen lege gebieden in de UITextView
.
Kan dit? Bij voorbaat dank!
Antwoord 1, autoriteit 100%
Voeg eerst een waarnemer toe voor de sleutelwaarde contentSize
van de UITextView
wanneer de weergave is geladen:
- (void) viewDidLoad {
[textField addObserver:self forKeyPath:@"contentSize" options:(NSKeyValueObservingOptionNew) context:NULL];
[super viewDidLoad];
}
Voeg vervolgens deze methode toe om de contentOffset
aan te passen telkens wanneer de waarde van contentSize
verandert:
-(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};
}
Antwoord 2, autoriteit 90%
Omdat UIKit niet KVO-compatibel is, heb ik besloten dit te implementeren als een subklasse van UITextView
die wordt bijgewerkt wanneer de contentSize
verandert.
Het is een licht aangepaste versie van Carlos’ antwoorddie de contentInset
in plaats van de contentOffset
. Behalve dat het compatibel is met iOS 9, lijkt het ook minder buggy te zijn op 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)
}
}
}
Antwoord 3, autoriteit 42%
Als je KVO niet wilt gebruiken, kun je de offset ook handmatig aanpassen door deze code te exporteren naar een functie als deze:
-(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);
}
en het aanroepen
-(void)textViewDidChange:(UITextView *)textView{
[self adjustContentSize:textView];
}
en elke keer dat u de tekst in de code bewerkt. Vergeet niet de controller in te stellen als de gedelegeerde
Swift 3-versie:
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)
}
Antwoord 4, autoriteit 32%
Voor iOS 9.0.2. we moeten in plaats daarvan de contentInset instellen. Als we de contentOffset KVO, zet iOS 9.0.2 deze op het laatste moment op 0, waardoor de wijzigingen in contentOffset worden genegeerd.
-(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];
}
Ik heb 0,0 en 0 gebruikt voor respectievelijk de linker-, onder- en rechterrand. Zorg ervoor dat u die ook berekent voor uw gebruiksscenario.
Antwoord 5, autoriteit 18%
Je kunt het rechtstreeks instellen met alleen beperkingen:
Er zijn 3 beperkingen die ik heb toegevoegd om tekst verticaal en horizontaal uit te lijnen in beperkingen zoals hieronder:
- Maak hoogte 0 en voeg beperkingen toe die groter zijn dan
- Verticaal uitlijnen toevoegen aan bovenliggende beperkingen
- Horizontaal uitlijnen toevoegen aan bovenliggende beperkingen
Antwoord 6, autoriteit 15%
Hier is een UITextView
-extensie die inhoud verticaal centreert:
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
}
}
Antwoord 7, autoriteit 13%
Ik heb zojuist een aangepaste verticaal gecentreerde tekstweergave gemaakt in 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-vertical-in-a-uitextview/
Antwoord 8, autoriteit 10%
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)
}
Antwoord 9, autoriteit 10%
Ik heb een tekstweergave die ik gebruik met autolayout en met het instellen van de lineFragmentPadding
en textContainerInset
op nul. Geen van de bovenstaande oplossingen werkte in mijn situatie. Dit werkt echter voor mij. Getest met 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
Antwoord 10, autoriteit 10%
Het is de eenvoudige taak om NSLayoutManager
te gebruiken om de echte tekstgrootte van de NSTextContainer
te krijgen
class VerticallyCenteredTextView: UITextView {
override func layoutSubviews() {
super.layoutSubviews()
let rect = layoutManager.usedRect(for: textContainer)
let topInset = (bounds.size.height - rect.height) / 2.0
textContainerInset.top = max(0, topInset)
}
}
Gebruik contentSize
en contentInset
niet in je uiteindelijke berekeningen.
Antwoord 11, autoriteit 8%
Ik heb ook dit probleem en ik heb het opgelost met een UITableViewCell
met UITextView
. Ik heb een methode gemaakt in een aangepaste UITableViewCell
-subklasse, eigenschap statusTextView
:
- (void)centerTextInTextView
{
CGFloat topCorrect = ([self.statusTextView bounds].size.height - [self.statusTextView contentSize].height * [self.statusTextView zoomScale])/2.0;
topCorrect = ( topCorrect < 0.0 ? 0.0 : topCorrect );
self.statusTextView.contentOffset = (CGPoint){ .x = 0, .y = -topCorrect };
En noem deze methode in methodes:
- (void)textViewDidBeginEditing:(UITextView *)textView
- (void)textViewDidEndEditing:(UITextView *)textView
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
Deze oplossing werkte voor mij zonder problemen, je kunt het proberen.
Antwoord 12, autoriteit 8%
Swift 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)
}
Antwoord 13, autoriteit 3%
Toevoegen aan Carlos-antwoord, voor het geval je tekst in tv groter dan tv-formaat hebt, hoef je de tekst niet opnieuw te plaatsen, dus verander deze code:
tv.contentOffset = (CGPoint){.x = 0, .y = -topCorrect};
naar dit:
if ([tv contentSize].height < [tv bounds].size.height) {
tv.contentOffset = (CGPoint){.x = 0, .y = -topCorrect};
}
Antwoord 14, autoriteit 3%
Oplossing voor automatische lay-out:
- Maak een UIView die fungeert als een container voor de UITextView.
- Voeg de volgende beperkingen toe:
- TextView: voorloopspatie uitlijnen met: container
- TextView: volg spatie uitlijnen met: container
- TextView: centreer Y uitlijnen op: container
- TextView: gelijke hoogte als: container, relatie: ≤
Antwoord 15, autoriteit 2%
Je kunt onderstaande code proberen, er is geen waarnemer verplicht. waarnemer gooit soms een fout wanneer de weergave wordt gedealloceerd.
U kunt deze code overal in viewDidLoad, viewWillAppear of in viewDidAppear bewaren.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
dispatch_async(dispatch_get_main_queue(), ^(void) {
UITextView *tv = txtviewDesc;
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};
});
});
Antwoord 16
Ik deed het als volgt: allereerst heb ik de UITextView ingesloten in een UIView (dit zou ook moeten werken voor mac OS). Vervolgens heb ik alle vier de zijden van de externe UIView aan de zijkanten van de container vastgemaakt, waardoor deze een vorm en grootte heeft die vergelijkbaar is met of gelijk is aan die van de UITextView. Zo had ik een goede container voor de UITextView. Vervolgens heb ik de linker- en rechterrand van de UITextView aan de zijkanten van de UIView vastgemaakt en de UITextView een hoogte gegeven. Ten slotte heb ik de UITextView verticaal gecentreerd in de UIView. Bingo 🙂 nu is de UITextView verticaal gecentreerd in de UIView, dus tekst in de UITextView is ook verticaal gecentreerd.
Antwoord 17
UITextView+VerticalAlignment.h
// UITextView+VerticalAlignment.h
// (c) The Internet 2015
#import <UIKit/UIKit.h>
@interface UITextView (VerticalAlignment)
- (void)alignToVerticalCenter;
- (void)disableAlignment;
@end
UITextView+VerticalAlignment.m
#import "UITextView+VerticalAlignment.h"
@implementation UITextView (VerticalAlignment)
- (void)alignToVerticalCenter {
[self addObserver:self forKeyPath:@"contentSize" options:NSKeyValueObservingOptionNew context:NULL];
}
- (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};
}
- (void)disableAlignment {
[self removeObserver:self forKeyPath:@"contentSize"];
}
@end
Antwoord 18
Ik heb dit probleem opgelost door een verticale verlenging tot middenhoogte te maken.
SWIFT 5:
extension UITextView {
func centerContentVertically() {
let fitSize = CGSize(width: bounds.width, height: CGFloat.greatestFiniteMagnitude)
let size = sizeThatFits(fitSize)
let heightOffset = (bounds.size.height - size.height * zoomScale) / 2
let positiveTopOffset = max(0, heightOffset)
contentOffset.y = -positiveTopOffset
}
}
Antwoord 19
Oplossing voor iOS10 in RubyMotion:
class VerticallyCenteredTextView < UITextView
def init
super
end
def layoutSubviews
self.recenter
end
def recenter
contentSize = self.sizeThatFits(CGSizeMake(self.bounds.size.width, Float::MAX))
topCorrection = (self.bounds.size.height - contentSize.height * self.zoomScale) / 2.0;
topCorrection = 0 if topCorrection < 0
self.contentInset = UIEdgeInsetsMake(topCorrection, 0, 0, 0)
end
end