アプリのUILabelビューでテキストを垂直方向に揃えようとしています。問題は、テキストを上に垂直に配置し、ラベルのサイズを280 x150にしたいことです。これら2つのことのいずれかしか達成できません。行を削除した場合
[myLabel sizeToFit];
その後、テキストの配置は問題ありませんが、サイズがめちゃくちゃになります。しかし、上記の行を追加すると、配置が乱れますが、サイズは問題ありません。この問題を解決するにはどうすればよいですか。
以下のコードを追加しました-
CGRect labelFrame = CGRectMake(22, 50, 280, 150);
UILabel *myLabel = [[UILabel alloc] initWithFrame:labelFrame];
[myLabel setText:finalRecipe];
[myLabel setBackgroundColor: [UIColor lightGrayColor]];
[myLabel setNumberOfLines:0];
[myLabel sizeToFit];
[self.view addSubview:myLabel];
私はFXLabelの作者であり、マニッシュを知りませんが、彼が助けようとしていたと思います(彼が私を宣伝していた場合、私は確かに彼に頼みませんでした、そして私は彼に支払いをしていません-ごめんなさいマニッシュ!)。
FXLabelの機能の1つは、InterfaceBuilderで設定されているラベルのUIContentModeプロパティを尊重することです。これは、label.contentMode = UIViewContentModeTop;を設定できることを意味します。テキストをラベルビューの上部に揃えます(通常のUILabelでは機能しません)。関連する例は次のとおりです。
https://github.com/nicklockwood/FXLabel/tree/master/Examples/Text%20Alignment
FXLabelはUILabelのドロップインサブクラスであるため、提起されている質問に対するかなり良い解決策だと思います。ただし、投稿者がサードパーティのライブラリ(理解できる)を使用せずに問題を解決したい場合は、次のコードを使用してください。
CGRect labelFrame = CGRectMake(22, 50, 280, 150);
UILabel *myLabel = [[UILabel alloc] initWithFrame:labelFrame];
[myLabel setText:finalRecipe];
[myLabel setBackgroundColor: [UIColor lightGrayColor]];
[myLabel setNumberOfLines:0];
CGFloat fontSize = 0.0f;
labelFrame.size = [myLabel.text sizeWithFont:myLabel.font
minFontSize:myLabel.minimumFontSize
actualFontSize:&fontSize
forWidth:labelFrame.width
lineBreakMode:myLabel.lineBreakMode];
myLabel.frame = labelFrame;
[self.view addSubview:myLabel];
注:(これはテストされていないため、タイプミスがある場合はお詫びします)
これにはUILabel
を使用しないでください。 UIButton
をUserInteractionEnabled = NO;
と一緒に使用すると、テキストを垂直方向または水平方向に揃えることができます。
どうぞ:
btnDetail.titleLabel?.numberOfLines = 5
btnDetail.titleLabel?.lineBreakMode = .byCharWrapping
btnDetail.contentVerticalAlignment = .top
btnDetail.contentHorizontalAlignment = .left
btnDetail.isUserInteractionEnabled = false
btnDetail.autoresizesSubviews = true
btnDetail.autoresizingMask = .flexibleWidth
[btnDetail.titleLabel setNumberOfLines:5];
[btnDetail.titleLabel setLineBreakMode:NSLineBreakByCharWrapping];
[btnDetail setContentVerticalAlignment:UIControlContentVerticalAlignmentTop];
[btnDetail setContentHorizontalAlignment:UIControlContentHorizontalAlignmentLeft];
[btnDetail setUserInteractionEnabled:NO];
btnDetail.autoresizesSubviews = YES;
btnDetail.autoresizingMask = UIViewAutoresizingFlexibleWidth;
UILabelをサブクラス化する必要があります。これを試して:
- (void)drawTextInRect:(CGRect)rect
{
CGSize sizeThatFits = [self sizeThatFits:rect.size];
rect.size.height = MIN(rect.size.height, sizeThatFits.height);
[super drawTextInRect:rect];
}
お気づきのとおり、UILabelはテキストをその境界内で垂直方向に中央揃えにします。ここで私たちは-sizeThatFits
はテキストブロックサイズであり、これを使用してUILabelに渡される描画長方形を制約し、テキストがラベル境界の上部から描画されるようにします。
次のように、無視された(ため息)contentMode
プロパティをサポートすることもできます。
- (void)drawTextInRect:(CGRect)rect
{
CGSize sizeThatFits = [self sizeThatFits:rect.size];
if (self.contentMode == UIViewContentModeTop) {
rect.size.height = MIN(rect.size.height, sizeThatFits.height);
}
else if (self.contentMode == UIViewContentModeBottom) {
rect.Origin.y = MAX(0, rect.size.height - sizeThatFits.height);
rect.size.height = MIN(rect.size.height, sizeThatFits.height);
}
[super drawTextInRect:rect];
}
ここには他にもたくさんの解決策と議論があります: ILabel内でテキストを垂直に上に揃えます
Swiftでは、UILabel
をサブクラス化し、drawTextInRect
をオーバーライドし、UIViewContentMode
に準拠するJRCのソリューションは次のようになります。
class AlignableUILabel: UILabel {
override func drawText(in rect: CGRect) {
var newRect = CGRect(x: rect.Origin.x,y: rect.Origin.y,width: rect.width, height: rect.height)
let fittingSize = sizeThatFits(rect.size)
if contentMode == UIViewContentMode.top {
newRect.size.height = min(newRect.size.height, fittingSize.height)
} else if contentMode == UIViewContentMode.bottom {
newRect.Origin.y = max(0, newRect.size.height - fittingSize.height)
}
super.drawText(in: newRect)
}
}
実装は単に次の問題です。
yourLabel.contentMode = UIViewContentMode.top
私にとって、それは魅力のように機能しました。
サブクラス化せずに、ボタンを使用したり、独自のボタンを使用したりする方法があります。
行数を0に設定してから、sizeToFitを呼び出します。
[label setNumberOfLines:0];
[label sizeToFit];
他の誰かがリンクしていると思うので、ここで詳細を説明します: ILabel内でテキストを垂直方向に上に揃えます
あなたはインターフェースビルダーの制約でそれを作ることができます。
これがお役に立てば幸いです。
ナイスハック...私の2セントSwift 4.2/5:
self.optTextMessage.numberOfLines = 0
self.optTitle.lineBreakMode = .byWordWrapping
提案されているように\ n ..を追加します。
私はあなたが望むことをカテゴリーを実装することによって行いました:
.h
@interface UILabel (VerticalAlign)
- (void)alignTop;
- (void)alignBottom;
@end
.m
@implementation UILabel (VerticalAlign)
#pragma mark
#pragma mark - Align Methods
- (void)alignTop
{
[self setFrame:[self newLabelFrame:UIControlContentVerticalAlignmentTop]];
}
- (void)alignBottom
{
[self setFrame:[self newLabelFrame:UIControlContentVerticalAlignmentBottom]];
}
#pragma mark
#pragma mark - Helper Methods
- (CGRect)newLabelFrame:(UIControlContentVerticalAlignment)alignment
{
CGRect labelRect = self.frame;
NSStringDrawingOptions options = NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingTruncatesLastVisibleLine | NSStringDrawingUsesFontLeading;
CGRect textRect = [self.text boundingRectWithSize:CGSizeMake(227.f, CGFLOAT_MAX)
options:options
attributes:@{NSFontAttributeName:self.font}
context:nil];
CGFloat textOffset = labelRect.size.height - textRect.size.height;
UIEdgeInsets contentInsets;
if (alignment == UIControlContentVerticalAlignmentTop)
{
if (textOffset < (labelRect.size.height/2.f))
{
contentInsets = UIEdgeInsetsMake(-textOffset, 0.f, 0.f, 0.f);
}
else
{
contentInsets = UIEdgeInsetsMake(0.f, 0.f, textOffset, 0.f);
}
}
else
{
if (textOffset < (labelRect.size.height/2.f))
{
contentInsets = UIEdgeInsetsMake(0.f, 0.f, -textOffset, 0.f);
}
else
{
contentInsets = UIEdgeInsetsMake(textOffset, 0.f, 0.f, 0.f);
}
}
return UIEdgeInsetsInsetRect(labelRect, contentInsets);
}
@end
「NumberOfLines」を0に設定する必要があることに注意してください。この例は、複数行オプションで機能します。
上記のカテゴリを実装した後、次の操作を実行できます。
[myLabel setText:finalRecipe];
[myLabel alignTop];
乾杯!