簡體   English   中英

IOS:使用自動布局根據標題文本調整 UIButton 高度?

[英]IOS: Adjust UIButton height depend on title text using Autolayout?

我有一個UIButton ,它可以在運行時更改標題。 因此,我想通過使用AutoLayout根據標題文本增加UIButton高度以顯示全文。

我可以通過將height constraint設置為“大於或等於”來增加UILabel高度,但它不適用於UIButton
我使用過[myButton sizeToFit]但它只增加了UIButon寬度(不增加高度)。

我當前的UIButton屬性現在是
- 約束高度:30 - 前導:15 - 尾隨:15 - 頂部:5 - 字體大小:12

更新
我為UIButton約束高度創建了一個 IBOutlet,用於更改@NSNood所說的高度。
然后我需要在標題文本中使用\\n來分割線。
但我不知道我應該把\\n放在哪里?

這是我想要的縱向Button

在此處輸入圖片說明

這是我想要的橫向Button 在此處輸入圖片說明

如何確定放置\\n

請指導我如何使用AutoLayout實現它。 任何幫助,將不勝感激。

抱歉,我最近沒有關注該帖子,因此我想出了一個真正遲到的解決方案。 如果將來有人可能會發現它有用,我仍然將答案寫為參考。

首先讓我們展示按鈕的故事板配置。 如下圖所示:

約束配置

圖片顯示我只為按鈕添加了左、上和右約束,沒有其他任何內容。 這允許按鈕的高度有一些intrinsicContentSize ,但它的寬度仍然由它的左右約束決定。

下一階段是編寫一些包含按鈕的 ViewController 類。 在我的 VC 中,我按名稱button為按鈕創建了一個插座:

@property(nonatomic,weak) IBOutlet UIButton* button;

並將其附加到故事板按鈕上。 現在我重寫了兩個方法,即viewDidLoadviewWillLayoutSubviews如下所示:

-(void)viewDidLoad {
    [super viewDidLoad];

    self.button.titleLabel.numberOfLines = 0;
    self.button.titleLabel.lineBreakMode = NSLineBreakByWordWrapping;
}
-(void)viewWillLayoutSubviews {
    [super viewWillLayoutSubviews];

    [self.button setTitle:@"Chapter One\n "
     "A Stop on the Salt Route\n "
     "1000 B.C.\n "
     "As they rounded a bend in the path that ran beside the river, Lara recognized the silhouette of a fig tree atop a nearby hill. The weather was hot and the days were long. The fig tree was in full leaf, but not yet bearing fruit." forState:UIControlStateNormal];
}
  1. viewDidLoad方法確保titleLabel (保存按鈕文本的標簽)是多行的,如果遇到一些大文本,它會通過包裝文字來包裝文本。
  2. viewWillLayoutSubviews方法確保在主視圖的邊界發生變化時發生按鈕布局過程,例如由於界面方向的變化。

最后也是最有效的部分是手動處理按鈕的布局過程。 為此,我們需要UIButton 我編寫了一個繼承自UIButton名為MyButton的子類,您可以使用任何您喜歡的名稱。 將此設置為 Identity Inspector 中按鈕的自定義類。

子類覆蓋了兩個方法,即intrinsicContentSizelayoutSubviews 類主體如下所示:

#import "MyButton.h"

@implementation MyButton

-(CGSize)intrinsicContentSize {
    return [self.titleLabel sizeThatFits:CGSizeMake(self.titleLabel.preferredMaxLayoutWidth, CGFLOAT_MAX)];;
}
-(void)layoutSubviews {
    self.titleLabel.preferredMaxLayoutWidth = self.frame.size.width;
    [super layoutSubviews];
}
@end

UIButon子類通過覆蓋layoutSubviews方法獲取布局過程的所有權。 這里的基本思想是確定按鈕寬度,一旦它已經布局。 然后將寬度設置為它的子titleLabel (保存按鈕文本的標簽)的preferredMaxLayoutWidth (布局引擎的最大寬度,多行標簽應該占據)。 最后,根據titleLabel的大小為按鈕返回一個intrinsicContentSize大小,以便按鈕完全包裹它的titleLabel

  1. 當按鈕已經布局並確定其框架大小時,將調用覆蓋的layoutSubviews 在它的第一個步驟中,按鈕的呈現寬度被設定為preferredMaxLayoutWidth按鈕的的titleLabel
  2. 第二步通過調用[super layoutSubviews]重新調用布局引擎,以便按鈕的intrinsicContentSize根據其titleLabelpreferredMaxLayoutWidth重新確定,此時該按鈕設置為按鈕呈現寬度。
  3. 在重寫的intrinsicContentSize方法中,我們返回完全包裹它的titleLabel並設置了preferredMaxLayoutWidth的按鈕的最小擬合大小。 我們在按鈕的titleLabel上使用sizeThatFits fits 方法,這只是因為titleLabel不遵循任何基於約束的布局。

結果應該與您可能需要的類似。

肖像 風景

請隨時讓我知道任何其他澄清/疑慮。

謝謝。

Swift 中的 Ayan Sengupta 解決方案,支持 contentEdgeInsets(感謝 Claus Jørgensen):

(如果需要,您還可以進一步自定義代碼以將titleEdgeInsets考慮在內)

  1. 子類化您的 UIButton 以獲取布局過程的所有權:

     /// https://stackoverflow.com/a/50575588/1033581 class AutoLayoutButton: UIButton { override var intrinsicContentSize: CGSize { var size = titleLabel!.sizeThatFits(CGSize(width: titleLabel!.preferredMaxLayoutWidth - contentEdgeInsets.left - contentEdgeInsets.right, height: .greatestFiniteMagnitude)) size.height += contentEdgeInsets.left + contentEdgeInsets.right return size } override func layoutSubviews() { titleLabel?.preferredMaxLayoutWidth = frame.size.width super.layoutSubviews() } }
  2. 在你的故事板中使用這個類,並為領先、尾隨、頂部、底部設置約束。 但不要設置任何高度約束。

另一種沒有子類化的替代方法是添加一個包裝視圖,如Bartłomiej Semańczyk 的回答Timur Bernikowich 評論所建議的。

關鍵是,如果您設置sizeToFit屬性,那么文本將始終在一行中並且按鈕的寬度將增加,除非您放置下一行符號\\n來明確表示您希望它是幾行。

你把 '\\n' 放在第一行的末尾,比如"line \\n line" ,它代表

line
line

如果您想為縱向橫向使用兩個不同的字符串值( \\n定位不同),您可以使用此處描述的UIDeviceOrientation ( UIDevice.currentDevice.orientation ) 檢查方向條件並根據設備的方向設置一個字符串值

有一種方法我一直用:

  1. 添加另一個引用 UILabel 其中 lineNumber=0 和與目標按鈕相同的寬度。
  2. 不要為 ref-UILable 設置高度約束,應該為按鈕設置高度約束以調整其高度
  3. 使用 button.titleLable、sizeTofit 將相同的文本設置為 ref UILabel 並獲取其 frame.size.height
  4. 將高度值用於目標按鈕的高度約束。 (當然,button.titleLabel linenumber 應該設置為0或更多行)

完畢。 :)

PS1。 這種方式可用於滾動視圖中的按鈕和引用標簽。

PS2。 在某些情況下,我們無法獲得 ref-label 的正確高度,因為它無法在 scrollview 中獲得正確的 frame.width,尤其是當我們使用拖尾約束時。 我們可以考慮在 sizeTofit 之前為 ref-label 定義一個固定寬度,並獲得目標按鈕使用的正確高度。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM