nibファイルに1つのラベルを追加しました。次に、そのラベルを左上に配置する必要があります。実行時にテキストを提供しているので、行数がわかりません。したがって、テキストに1行しか含まれていない場合は、垂直方向に中央揃えで表示されます。その配置は、その前にある私のそれぞれのラベルと一致していません。
例えば:
奇妙に見えます:(
ラベルテキストを左上揃えに適切に設定する方法はありますか?
nibファイルに1つのラベルを追加しました。次に、そのラベルを左上に配置する必要があります。実行時にテキストを提供しているので、行数がわかりません。したがって、テキストに1行しか含まれていない場合は、垂直方向に中央揃えで表示されます。その配置は、その前にある私のそれぞれのラベルと一致していません。
例えば:
奇妙に見えます:(
ラベルテキストを左上揃えに適切に設定する方法はありますか?
かなり簡単です。プロパティとオーバーライドを使用してUILabel
サブクラスを作成し、上、中、または下の垂直方向の配置の正しい境界を返します。コードは次のとおりです。verticalAlignment
textRectForBounds:limitedToNumberOfLines
SOLabel.h
#import <UIKit/UIKit.h>
typedef enum
{
VerticalAlignmentTop = 0, // default
VerticalAlignmentMiddle,
VerticalAlignmentBottom,
} VerticalAlignment;
@interface SOLabel : UILabel
@property (nonatomic, readwrite) VerticalAlignment verticalAlignment;
@end
SOLabel.m
@implementation SOLabel
-(id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (!self) return nil;
// set inital value via IVAR so the setter isn't called
_verticalAlignment = VerticalAlignmentTop;
return self;
}
-(VerticalAlignment) verticalAlignment
{
return _verticalAlignment;
}
-(void) setVerticalAlignment:(VerticalAlignment)value
{
_verticalAlignment = value;
[self setNeedsDisplay];
}
// align text block according to vertical alignment settings
-(CGRect)textRectForBounds:(CGRect)bounds
limitedToNumberOfLines:(NSInteger)numberOfLines
{
CGRect rect = [super textRectForBounds:bounds
limitedToNumberOfLines:numberOfLines];
CGRect result;
switch (_verticalAlignment)
{
case VerticalAlignmentTop:
result = CGRectMake(bounds.origin.x, bounds.origin.y,
rect.size.width, rect.size.height);
break;
case VerticalAlignmentMiddle:
result = CGRectMake(bounds.origin.x,
bounds.origin.y + (bounds.size.height - rect.size.height) / 2,
rect.size.width, rect.size.height);
break;
case VerticalAlignmentBottom:
result = CGRectMake(bounds.origin.x,
bounds.origin.y + (bounds.size.height - rect.size.height),
rect.size.width, rect.size.height);
break;
default:
result = bounds;
break;
}
return result;
}
-(void)drawTextInRect:(CGRect)rect
{
CGRect r = [self textRectForBounds:rect
limitedToNumberOfLines:self.numberOfLines];
[super drawTextInRect:r];
}
@end
再説明するのではなく、このかなり広範で評価の高い質問/回答にリンクします。
簡単な答えはノーです。Appleはこれを簡単にしませんでしたが、フレームサイズを変更することで可能になります。
SOLabelは私のために働きます。
このバージョンは、RTL言語をサポートできるように、元のバージョンから更新されています。
public class VerticalAlignLabel: UILabel {
enum VerticalAlignment {
case top
case middle
case bottom
}
var verticalAlignment : VerticalAlignment = .top {
didSet {
setNeedsDisplay()
}
}
override public func textRect(forBounds bounds: CGRect, limitedToNumberOfLines: Int) -> CGRect {
let rect = super.textRect(forBounds: bounds, limitedToNumberOfLines: limitedToNumberOfLines)
if UIView.userInterfaceLayoutDirection(for: .unspecified) == .rightToLeft {
switch verticalAlignment {
case .top:
return CGRect(x: self.bounds.size.width - rect.size.width, y: bounds.origin.y, width: rect.size.width, height: rect.size.height)
case .middle:
return CGRect(x: self.bounds.size.width - rect.size.width, y: bounds.origin.y + (bounds.size.height - rect.size.height) / 2, width: rect.size.width, height: rect.size.height)
case .bottom:
return CGRect(x: self.bounds.size.width - rect.size.width, y: bounds.origin.y + (bounds.size.height - rect.size.height), width: rect.size.width, height: rect.size.height)
}
} else {
switch verticalAlignment {
case .top:
return CGRect(x: bounds.origin.x, y: bounds.origin.y, width: rect.size.width, height: rect.size.height)
case .middle:
return CGRect(x: bounds.origin.x, y: bounds.origin.y + (bounds.size.height - rect.size.height) / 2, width: rect.size.width, height: rect.size.height)
case .bottom:
return CGRect(x: bounds.origin.x, y: bounds.origin.y + (bounds.size.height - rect.size.height), width: rect.size.width, height: rect.size.height)
}
}
}
override public func drawText(in rect: CGRect) {
let r = self.textRect(forBounds: rect, limitedToNumberOfLines: self.numberOfLines)
super.drawText(in: r)
}
}
class UIVerticalAlignLabel: UILabel {
enum VerticalAlignment : Int {
case VerticalAlignmentTop = 0
case VerticalAlignmentMiddle = 1
case VerticalAlignmentBottom = 2
}
var verticalAlignment : VerticalAlignment = .VerticalAlignmentTop {
didSet {
setNeedsDisplay()
}
}
required init(coder aDecoder: NSCoder){
super.init(coder: aDecoder)
}
override func textRectForBounds(bounds: CGRect, limitedToNumberOfLines: Int) -> CGRect {
let rect = super.textRectForBounds(bounds, limitedToNumberOfLines: limitedToNumberOfLines)
switch(verticalAlignment) {
case .VerticalAlignmentTop:
return CGRectMake(bounds.origin.x, bounds.origin.y, rect.size.width, rect.size.height)
case .VerticalAlignmentMiddle:
return CGRectMake(bounds.origin.x, bounds.origin.y + (bounds.size.height - rect.size.height) / 2, rect.size.width, rect.size.height)
case .VerticalAlignmentBottom:
return CGRectMake(bounds.origin.x, bounds.origin.y + (bounds.size.height - rect.size.height), rect.size.width, rect.size.height)
default:
return bounds
}
}
override func drawTextInRect(rect: CGRect) {
let r = self.textRectForBounds(rect, limitedToNumberOfLines: self.numberOfLines)
super.drawTextInRect(r)
}
}
あなたのコードで
label.text = @"some text";
[label sizeToFit];
これをテーブルセルや別のデータでリサイクルされる他のビューで使用する場合は、sizeToFitを呼び出す前に、元のフレームをどこかに保存してリセットする必要があることに注意してください。
同じ問題の別の解決策を見つけました。UITextView
代わりに使用し、機能をにUILabel
切り替えました。editable()
false
私もこの問題を抱えていましたが、UILabelのプロパティとメソッドを設定する順序が重要であることがわかりました。
[label sizeToFit]
以前に電話をかけた場合label.font = [UIFont fontWithName:@"Helvetica" size:14];
、テキストは上に揃えられませんが、入れ替えると、揃えられます。
また、最初にテキストを設定すると違いが生じることにも気づきました。
お役に立てれば。
Interface Builderを使用しているので、ラベルの制約を設定します(高さと幅も必ず設定してください)。次に、サイズインスペクターで、ラベルの高さを確認します。そこでは、=の代わりに>=を読み取る必要があります。次に、そのView Controllerの実装で、行数を0に設定し(IBでも実行可能)、ラベル[labelsizeToFit]を設定します。テキストの長さが長くなると、ラベルの高さが増し、テキストが左上に表示されます。
必要なのがデフォルトで左上隅から始まる編集不可能なテキストである場合は、ラベルの代わりにテキストビューを使用して、次のようにその状態を編集不可能に設定できます。
textview.isEditable = false
ラベルをいじるよりもずっと簡単です...
乾杯!
SoLabelを使用したソリューションは機能します、ありがとう。
ベロー私はモノタッチバージョンを追加しました:
public class UICustomLabel : UILabel
{
private UITextVerticalAlignment _textVerticalAlignment;
public UICustomLabel()
{
TextVerticalAlignment = UITextVerticalAlignment.Top;
}
public UITextVerticalAlignment TextVerticalAlignment
{
get
{
return _textVerticalAlignment;
}
set
{
_textVerticalAlignment = value;
SetNeedsDisplay();
}
}
public override void DrawText(RectangleF rect)
{
var bound = TextRectForBounds(rect, Lines);
base.DrawText(bound);
}
public override RectangleF TextRectForBounds(RectangleF bounds, int numberOfLines)
{
var rect = base.TextRectForBounds(bounds, numberOfLines);
RectangleF resultRect;
switch (TextVerticalAlignment)
{
case UITextVerticalAlignment.Top:
resultRect = new RectangleF(bounds.X, bounds.Y, rect.Size.Width, rect.Size.Height);
break;
case UITextVerticalAlignment.Middle:
resultRect = new RectangleF(bounds.X,
bounds.Y + (bounds.Size.Height - rect.Size.Height)/2,
rect.Size.Width, rect.Size.Height);
break;
case UITextVerticalAlignment.Bottom:
resultRect = new RectangleF(bounds.X,
bounds.Y + (bounds.Size.Height - rect.Size.Height),
rect.Size.Width, rect.Size.Height);
break;
default:
resultRect = bounds;
break;
}
return resultRect;
}
}
public enum UITextVerticalAlignment
{
Top = 0, // default
Middle,
Bottom
}
最も簡単で簡単な方法は、StackViewにラベルを埋め込み、ここに示すように、ストーリーボードの属性インスペクターでStackViewの軸を水平に設定し、位置合わせを上に設定することです。
totiGのすばらしい答えに基づいて、ストーリーボードからUILabelの垂直方向の配置を非常に簡単にカスタマイズできるIBDesignableクラスを作成しました。StoryBoardIDインスペクターからUILabelのクラスを「VerticalAlignLabel」に設定していることを確認してください。垂直方向の配置が有効にならない場合は、[エディター]->[すべてのビューを更新]に移動します。
仕組み:UILabelのクラスを正しく設定すると、ストーリーボードに整数(配置コード)を受け取る入力フィールドが表示されます。
更新:中央に配置されたラベルのサポートを追加しました〜Sev
上揃えに0を入力します
MiddleAlignmentに1を入力します
下揃えに2を入力します
@IBDesignable class VerticalAlignLabel: UILabel {
@IBInspectable var alignmentCode: Int = 0 {
didSet {
applyAlignmentCode()
}
}
func applyAlignmentCode() {
switch alignmentCode {
case 0:
verticalAlignment = .top
case 1:
verticalAlignment = .topcenter
case 2:
verticalAlignment = .middle
case 3:
verticalAlignment = .bottom
default:
break
}
}
override func awakeFromNib() {
super.awakeFromNib()
self.applyAlignmentCode()
}
override func prepareForInterfaceBuilder() {
super.prepareForInterfaceBuilder()
self.applyAlignmentCode()
}
enum VerticalAlignment {
case top
case topcenter
case middle
case bottom
}
var verticalAlignment : VerticalAlignment = .top {
didSet {
setNeedsDisplay()
}
}
override public func textRect(forBounds bounds: CGRect, limitedToNumberOfLines: Int) -> CGRect {
let rect = super.textRect(forBounds: bounds, limitedToNumberOfLines: limitedToNumberOfLines)
if #available(iOS 9.0, *) {
if UIView.userInterfaceLayoutDirection(for: .unspecified) == .rightToLeft {
switch verticalAlignment {
case .top:
return CGRect(x: self.bounds.size.width - rect.size.width, y: bounds.origin.y, width: rect.size.width, height: rect.size.height)
case .topcenter:
return CGRect(x: self.bounds.size.width - (rect.size.width / 2), y: bounds.origin.y, width: rect.size.width, height: rect.size.height)
case .middle:
return CGRect(x: self.bounds.size.width - rect.size.width, y: bounds.origin.y + (bounds.size.height - rect.size.height) / 2, width: rect.size.width, height: rect.size.height)
case .bottom:
return CGRect(x: self.bounds.size.width - rect.size.width, y: bounds.origin.y + (bounds.size.height - rect.size.height), width: rect.size.width, height: rect.size.height)
}
} else {
switch verticalAlignment {
case .top:
return CGRect(x: bounds.origin.x, y: bounds.origin.y, width: rect.size.width, height: rect.size.height)
case .topcenter:
return CGRect(x: (self.bounds.size.width / 2 ) - (rect.size.width / 2), y: bounds.origin.y, width: rect.size.width, height: rect.size.height)
case .middle:
return CGRect(x: bounds.origin.x, y: bounds.origin.y + (bounds.size.height - rect.size.height) / 2, width: rect.size.width, height: rect.size.height)
case .bottom:
return CGRect(x: bounds.origin.x, y: bounds.origin.y + (bounds.size.height - rect.size.height), width: rect.size.width, height: rect.size.height)
}
}
} else {
// Fallback on earlier versions
return rect
}
}
override public func drawText(in rect: CGRect) {
let r = self.textRect(forBounds: rect, limitedToNumberOfLines: self.numberOfLines)
super.drawText(in: r)
}
}
UILabelをUITextViewに変更することもできます。これは、UITextViewの利点がテキストが自動的に左上に配置されることを除いて、基本的に同じことを行うためです。
UILabelの代わりにUITextViewを使用します。また、UITableViewCellの幅の自動行の高さでも機能します
isScrollEnabledとisEditableをfalseに設定します。TextViewの最小高さ制約を追加します
final class TestVC: UIViewController {
lazy var testTextLabel: UITextView = {
$0.isScrollEnabled = false
$0.isEditable = false
$0.font = .systemFont(ofSize: 17, weight: .medium)
$0.textColor = .black
$0.layer.borderWidth = 1
$0.layer.borderColor = UIColor.black.cgColor
$0.layer.cornerRadius = 5
return $0
}(UITextView())
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
testTextLabel.text = "Your text"
view.addSubview(testTextLabel)
testTextLabel.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
testTextLabel.topAnchor.constraint(equalTo: testTextLabel.superview!.safeAreaLayoutGuide.topAnchor, constant: 12),
testTextLabel.leadingAnchor.constraint(equalTo: testTextLabel.superview!.leadingAnchor, constant: 12),
testTextLabel.widthAnchor.constraint(equalToConstant: 250),
testTextLabel.heightAnchor.constraint(greaterThanOrEqualToConstant: 70)
])
}
}
@totiGの答えのSwift3バージョン
class UIVerticalAlignLabel: UILabel {
enum VerticalAlignment : Int {
case VerticalAlignmentTop = 0
case VerticalAlignmentMiddle = 1
case VerticalAlignmentBottom = 2
}
@IBInspectable var verticalAlignment : VerticalAlignment = .VerticalAlignmentTop {
didSet {
setNeedsDisplay()
}
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override func textRect(forBounds bounds: CGRect, limitedToNumberOfLines: Int) -> CGRect {
let rect = super.textRect(forBounds: bounds, limitedToNumberOfLines: limitedToNumberOfLines)
switch(verticalAlignment) {
case .VerticalAlignmentTop:
return CGRect(x: bounds.origin.x, y: bounds.origin.y, width: rect.size.width, height: rect.size.height)
case .VerticalAlignmentMiddle:
return CGRect(x: bounds.origin.x, y: bounds.origin.y + (bounds.size.height - rect.size.height) / 2, width: rect.size.width, height: rect.size.height)
case .VerticalAlignmentBottom:
return CGRect(x: bounds.origin.x, y: bounds.origin.y + (bounds.size.height - rect.size.height), width: rect.size.width, height: rect.size.height)
}
}
override func drawText(in rect: CGRect) {
let r = self.textRect(forBounds: rect, limitedToNumberOfLines: self.numberOfLines)
super.drawText(in: r)
}
}
私はこの問題を抱えていますが、私のラベルはにUITableViewCell
あり、問題を解決する最も簡単な方法は、空を作成し、UIView
その中にラベルを上部と左側のみに制約を付けて設定することでした。 0までの行数
@totiGの答えは正解で、私の問題を解決しました。しかし、このメソッドの実装中に問題が見つかりました。5s、SEなどの小さなデバイスでは、これは機能しません。私は設定label.sizeToFit()
する必要がありますoverride func layoutSubViews()
override func layoutSubViews() {
super.layoutSubViews()
// Do other works if needed
label.sizeToFit()
}
textRect(forBounds:limitedToNumberOfLines:)を使用します
class TopAlignedLabel: UILabel {
override func drawText(in rect: CGRect) {
let textRect = super.textRect(forBounds: bounds, limitedToNumberOfLines: numberOfLines)
super.drawText(in: textRect)
}
}
iOS 7の場合、それは私が作って働いたものです
@implementation UILabel (VerticalAlign)
- (void)alignTop
{
CGSize boundingRectSize = CGSizeMake(self.frame.size.width, CGFLOAT_MAX);
NSDictionary *attributes = @{NSFontAttributeName : self.font};
CGRect labelSize = [self.text boundingRectWithSize:boundingRectSize options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading
attributes:attributes
context:nil];
int numberOfLines= ceil(labelSize.size.height / self.font.lineHeight);
CGRect newFrame = self.frame;
newFrame.size.height = numberOfLines * self.font.lineHeight;
self.frame = newFrame;
}
- (void)alignBottom
{
CGSize boundingRectSize = CGSizeMake(self.frame.size.width, CGFLOAT_MAX);
NSDictionary *attributes = @{NSFontAttributeName : self.font};
CGRect labelSize = [self.text boundingRectWithSize:boundingRectSize options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading
attributes:attributes
context:nil];
int numberOfLines= ceil(labelSize.size.height / self.font.lineHeight);
int numberOfNewLined = (self.frame.size.height/self.font.lineHeight) - numberOfLines;
NSMutableString *newLines = [NSMutableString string];
for(int i=0; i< numberOfNewLined; i++){
[newLines appendString:@"\n"];
}
[newLines appendString:self.text];
self.text = [newLines mutableCopy];
}
Swift 2.0::UILabel拡張機能の使用
空のSwiftファイルに一定の列挙値を作成します。
// AppRef.swift
import UIKit
import Foundation
enum UILabelTextPositions : String {
case VERTICAL_ALIGNMENT_TOP = "VerticalAlignmentTop"
case VERTICAL_ALIGNMENT_MIDDLE = "VerticalAlignmentMiddle"
case VERTICAL_ALIGNMENT_BOTTOM = "VerticalAlignmentBottom"
}
UILabel拡張機能の使用:
空のSwiftクラスを作成し、名前を付けます。以下を追加します。
// AppExtensions.swift
import Foundation
import UIKit
extension UILabel{
func makeLabelTextPosition (sampleLabel :UILabel?, positionIdentifier : String) -> UILabel
{
let rect = sampleLabel!.textRectForBounds(bounds, limitedToNumberOfLines: 0)
switch positionIdentifier
{
case "VerticalAlignmentTop":
sampleLabel!.frame = CGRectMake(bounds.origin.x+5, bounds.origin.y, rect.size.width, rect.size.height)
break;
case "VerticalAlignmentMiddle":
sampleLabel!.frame = CGRectMake(bounds.origin.x+5,bounds.origin.y + (bounds.size.height - rect.size.height) / 2,
rect.size.width, rect.size.height);
break;
case "VerticalAlignmentBottom":
sampleLabel!.frame = CGRectMake(bounds.origin.x+5, bounds.origin.y + (bounds.size.height - rect.size.height),rect.size.width, rect.size.height);
break;
default:
sampleLabel!.frame = bounds;
break;
}
return sampleLabel!
}
}
使用法 :
myMessageLabel.makeLabelTextPosition(messageLabel, positionIdentifier: UILabelTextPositions.VERTICAL_ALIGNMENT_TOP.rawValue)
スウィフト5
シンプルで、プロパティの順序がすべてです。
titleLabel.frame = CGRect(x: 20, y: 20, width: 374, height: 291.2)
titleLabel.backgroundColor = UIColor.clear //set a light color to see the frame
titleLabel.textAlignment = .left
titleLabel.lineBreakMode = .byTruncatingTail
titleLabel.numberOfLines = 4
titleLabel.font = UIFont(name: "HelveticaNeue-Bold", size: 35)
titleLabel.text = "Example"
titleLabel.sizeToFit()
self.view.addSubview(titleLabel)
layoutSubviewsで設定する必要があります。
override func layoutSubviews() {
super.layoutSubviews()
yourLabel.sizeToFit()
//yourLabel.center.x = someView.center.x // optionally if exists
}