2016-04-02 10 views
0

内容に応じてサイズ変更するカスタムラベル

私は最初からラベルを作成しています。 (私の最終目的は、モンゴル語の​​スクリプトの縦書きのラベルを作ることですが、今のところ、通常の横書きのラベルを練習として作成しています)。カスタムビューのフレームをその本質的なコンテンツサイズに一致させる方法

長さと幅の制​​約がない限り、ラベルのフレームは、その固有のコンテンツサイズに従ってサイズ変更されます。

それは、IBのすべてではIB

に作品は、私はUILabel、私のカスタムラベル(UIViewサブクラス)、およびボタンをテストする際に正常に動作しているようです。

これらのビューのそれぞれに上部および上部の制約を追加しますが、高さまたは幅の制約は設定しません。

enter image description here

私は(まだ任意の複数の制約を加えることなく)ストーリーボードにそれらのサイズを変更する場合は...

enter image description here

そして用ビュー内のすべてのビューをアップデートフレームを選択コントローラーでは、標準ラベルと私のカスタムラベルの両方が、固有のコンテンツサイズに合わせて適切にサイズ変更されます。私は、実行時にラベルのテキストを変更すると

enter image description here

これは、しかし、私のカスタムラベルの枠がリサイズされていない、実行中のアプリケーション

上では動作しません。 (私は一時的にライトブルーの背景色でカスタムラベルのフレームから、ここでそれを区別支援するために、テキストレイヤーにダークブルーのボーダーを追加しました。)

enter image description here

クリックすると、「変更のテキストは」

います

enter image description here

ご覧のとおり、テキストレイヤフレームは変更されましたが、カスタムビューのフレームは変更されませんでした。

コード

これは私のカスタムラベルクラスです:

import UIKit 
@IBDesignable 
class UILabelFromScratch: UIView { 

    private let textLayer = CATextLayer() 

    @IBInspectable var text: String = "" { 
     didSet { 
      updateTextLayerFrame() 
     } 
    } 

    @IBInspectable var fontSize: CGFloat = 17 { 
     didSet { 
      updateTextLayerFrame() 
     } 
    } 

    // MARK: - Initialization 

    override init(frame: CGRect) { 
     super.init(frame: frame) 
     setup() 
    } 

    required init?(coder: NSCoder) { 
     super.init(coder: coder) 
     setup() 
    } 

    func setup() { 

     // Text layer 
     textLayer.borderColor = UIColor.blueColor().CGColor 
     textLayer.borderWidth = 1 
     textLayer.contentsScale = UIScreen.mainScreen().scale 
     layer.addSublayer(textLayer) 
    } 

    // MARK: Other methods 

    override func intrinsicContentSize() -> CGSize { 
     return textLayer.frame.size 
    } 

    func updateTextLayerFrame() { 

     let myAttribute = [ NSFontAttributeName: UIFont.systemFontOfSize(fontSize) ] 
     let attrString = NSMutableAttributedString(string: self.text, attributes: myAttribute) 
     let size = dimensionsForAttributedString(attrString) 

     textLayer.frame = CGRect(x: self.layer.bounds.origin.x, y: self.layer.bounds.origin.y, width: size.width, height: size.height) 
     textLayer.string = attrString 

    } 

    func dimensionsForAttributedString(attrString: NSAttributedString) -> CGSize { 

     var ascent: CGFloat = 0 
     var descent: CGFloat = 0 
     var width: CGFloat = 0 
     let line: CTLineRef = CTLineCreateWithAttributedString(attrString) 
     width = CGFloat(CTLineGetTypographicBounds(line, &ascent, &descent, nil)) 

     // make width an even integer for better graphics rendering 
     width = ceil(width) 
     if Int(width)%2 == 1 { 
      width += 1.0 
     } 

     return CGSize(width: width, height: ceil(ascent+descent)) 
    } 
} 

そしてここView Controllerクラスです:

import UIKit 
class ViewController: UIViewController { 

    @IBOutlet weak var normalLabel: UILabel! 
    @IBOutlet weak var labelFromScratch: UILabelFromScratch! 

    @IBAction func changeTextButtonTapped(sender: UIButton) { 

     normalLabel.text = "Hello" 
     labelFromScratch.text = "Hello" 
    } 
} 

質問

UILabelがあることないこと、それを何ですか私はカスタムラベルに紛失していますか?

override func intrinsicContentSize() -> CGSize { 
    return textLayer.frame.size 
} 

は他に何私は何をする必要があります:私はintrinsicContentSizeをオーバーライド?

答えて

1

私はコードを一行も行方不明になった:

invalidateIntrinsicContentSize() 

私は、テキストレイヤーのフレームを更新した後にこれを追加しました。

func updateTextLayerFrame() { 

    // ... 

    textLayer.frame = CGRect(x: self.layer.bounds.origin.x, y: self.layer.bounds.origin.y, width: size.width, height: size.height) 
    invalidateIntrinsicContentSize() 

    // ... 
} 

documentationは言う何かが その固有のコンテンツのサイズを無効化するカスタムビューに変更し、この

コール。これにより、制約ベースのレイアウト システムは、次の レイアウトパスで、新しい組み込みコンテンツサイズを考慮に入れることができます。

:私はこの解決策を見つけ

関連する問題