[英]Wrap NSButton title
有什么方法可以讓 NSButton 標題在寬度長於按鈕寬度時換行,而不是被剪掉?
我正在嘗試使用一個單選按鈕,其中的文本可以很長並且有多行。 我考慮讓它工作的一種方法是使用 NSRadioButton 類型的 NSButton,但無法讓多行文本工作。
也許我最好的選擇是先有一個 NSButton,然后是一個 NSTextView,其上的 mouseDown 委托 function 會觸發 NSButton state?
我不相信你可以。 您必須NSButtonCell
才能添加對此的支持。
也就是說,在按鈕上包含多行文本通常是個壞主意。 按鈕 label 應該簡明地表示執行的操作:
按鈕上的 label 應該是一個動詞或動詞短語,描述它執行的操作——保存、關閉、打印、刪除、更改密碼等。 如果一個按鈕作用於單個設置,label 按鈕盡可能具體; 例如,“選擇圖片...”比“選擇...”更有幫助,因為按鈕會立即執行操作,因此在 label 中不必使用“現在”(例如,立即掃描)。
你想做什么?
我遲到了,但我仍然覺得有義務分享我的發現。
只需在按鈕標題前后添加一個換行符,然后再將其分配給實際按鈕 - 瞧。 它現在自動換行。
這種方法的缺點是,由於我不知道的原因,在某個版本的 OS X 上編譯的應用程序在新版本上運行時會向下移動一行。
好吧,這就是我需要多行按鈕的借口:我正在為 IBM 701 編寫一個仿真器,它帶有前面板,並且,祝福他們,該前面板的設計者使用了多行標簽。 這是我的代碼。 你只需要繼承 NSButtonCell(不是 NSButton),並且只需要重寫一個方法。
// In Xcode 4.6 (don't know about earlier versions): Place NSButton, then double-click it
// and change class NSButtonCell to ButtonMultiLineCell.
@interface ButtonMultiLineCell : NSButtonCell
@end
@implementation ButtonMultiLineCell
- (NSRect)drawTitle:(NSAttributedString *)title withFrame:(NSRect)frame inView:(NSView *)controlView
{
NSAttributedString *as = [[NSAttributedString alloc] initWithString:[title.string stringByReplacingOccurrencesOfString:@" " withString:@"\n"]];
NSFont *sysFont = [NSFont systemFontOfSize:10];
NSMutableParagraphStyle *paragraphStyle = [[[NSParagraphStyle defaultParagraphStyle] mutableCopy] autorelease];
[paragraphStyle setAlignment:NSCenterTextAlignment];
NSDictionary *attributes = [NSDictionary dictionaryWithObjectsAndKeys:
sysFont, NSFontAttributeName,
paragraphStyle, NSParagraphStyleAttributeName,
nil];
NSSize textSize = [as.string sizeWithAttributes:attributes];
NSRect textBounds = NSMakeRect(0, 0, textSize.width, textSize.height);
// using frame argument seems to produce text in wrong place
NSRect f = NSMakeRect(0, (controlView.frame.size.height - textSize.height) / 2, controlView.frame.size.width, textSize.height);
[as.string drawInRect:f withAttributes:attributes];
return textBounds; // not sure what rectangle to return or what is done with it
}
@end
即使是后來,但我也覺得有義務分享。 可以設置 NSButton 的 attributesTitle 屬性來實現手動換行。
就我而言,如果按鈕標題超過 6 個字符(Swift 3),我希望它換行:
if button.title.characters.count > 6 {
var wrappedTitle = button.title
wrappedTitle.insert("\n", at: wrappedTitle.index(wrappedTitle.startIndex, offsetBy: 6))
let style = NSMutableParagraphStyle()
style.alignment = .center
let attributes = [NSFontAttributeName: NSFont.systemFont(ofSize: 19), NSParagraphStyleAttributeName: style] as [String : Any]
button.attributedTitle = NSAttributedString(string: wrappedTitle, attributes: attributes)
}
截至今天,我看到這可以簡單地通過 NSButton 單元格上的屬性來完成:
myButton.cell?.wraps = true
我和索倫在一起; 如果您需要更長的描述,請考慮使用工具提示,或者如果描述性文本只有幾行,則使用單選選項下方的小系統字體將描述性文本放置在包裝的文本字段中。 否則,您可以在幫助文檔中提供更多信息。
不過,想辦法以簡潔的方式說出你需要說的話是你最好的選擇。
我遇到了同樣的問題,並帶着一顆沉淪的心嘗試了這篇文章中的解決方案。 (雖然我很欣賞關於通常應該保持按鈕標題簡短的建議,但我正在編寫游戲,並且我希望多行答案的行為類似於按鈕)。
有時,你不會從這里到達那里。 我的理想是一個帶有多行 label 的 NSButton,但由於我無法不費吹灰之力地得到它,所以我創建了一個 PseudoButton:一個 NSControl 子類,其行為類似於一個按鈕。 它有一只手 cursor 表示“你可以點擊這里”,它給出的反饋是:當你點擊鼠標時,它會變為 selectedControlColor,當你松開鼠標時,它會恢復正常。 與嘗試堆疊按鈕和標簽的解決方案不同,在視圖頂部放置標簽和圖像沒有問題:整個視圖都是可點擊區域。
import Cocoa
@IBDesignable
class PseudoButton: NSControl {
@IBInspectable var backgroundColor: NSColor = NSColor.white{
didSet{
self.needsDisplay = true
}
}
override func draw(_ dirtyRect: NSRect) {
super.draw(dirtyRect)
let path = NSBezierPath(rect: dirtyRect)
backgroundColor.setFill()
path.fill()
NSColor.black.setStroke()
path.lineWidth = 2
path.stroke()
}
override func mouseDown(with event: NSEvent) {
self.backgroundColor = NSColor.selectedControlColor
}
override func mouseUp(with event: NSEvent) {
self.backgroundColor = NSColor.clear
guard let action = action else {return}
tryToPerform(action, with: self)
//@IBAction func pseudobuttonClicked(_ sender: PseudoButton) in the ViewController class
}
override func resetCursorRects() {
addCursorRect(bounds, cursor: .pointingHand)
}
}
您可以像使用 storyboard 中的任何其他控件一樣使用它:將 Pseudobutton 拖入,隨意裝飾它,並將其連接到 viewController class 中的適當 IBAction。
我更喜歡這個,而不是干涉 NSCell。 (根據過去的經驗,基於 NSCell 的黑客攻擊更有可能被破解)。
這里有點晚了,這是我在標題中插入新行的代碼:
private func calculateMultipleLineTitle(_ title: String) -> String {
guard !title.isEmpty else { return title }
guard let cell = cell as? NSButtonCell else { return title }
let titleRect = cell.titleRect(forBounds: bounds)
let attr = attributedTitle.attributes(at: 0, effectiveRange: nil)
let indent = (attr[.paragraphStyle] as? NSMutableParagraphStyle)?.firstLineHeadIndent ?? 0
let titleTokenArray = title.components(separatedBy: " ") // word wrap break mode
guard !titleTokenArray.isEmpty else { return title }
var multipleLineTitle = titleTokenArray[0]
var multipleLineAttrTitle = NSMutableAttributedString(string: multipleLineTitle, attributes: attr)
var index = 1
while index < titleTokenArray.count {
multipleLineAttrTitle = NSMutableAttributedString(
string: multipleLineTitle + " " + titleTokenArray[index],
attributes: attr
)
if titleRect.minX+indent+multipleLineAttrTitle.size().width > bounds.width {
multipleLineTitle += " \n" + titleTokenArray[index]
} else {
multipleLineTitle += " " + titleTokenArray[index]
}
index += 1
}
return multipleLineTitle
}
只需將原始標題作為參數傳遞,它將返回多行標題。
我在標題的末尾添加了一個“\n”,我正在使用 NSAttributedString 設置標題。 這為我解決了問題。 我在 MacOS Big Sur 11.7.2、Xcode 13.12.1
private NSAttributedString GetAttributedString(string text)
{
var paragraph = new NSMutableParagraphStyle();
paragraph.Alignment = NSTextAlignment.Center;
paragraph.LineBreakMode = NSLineBreakMode.ByWordWrapping;
var attrString = new NSAttributedString
(
text + "\n",
font: NSFont.FromFontName("Arial", 50.0f),
foregroundColor: NSColor.White,
backgroundColor: NSColor.FromCalibratedRgba(0, 0, 0, 0.0f),
paragraphStyle: paragraph
);
return attrString;
}
textButton.AttributedTitle = GetAttributedString("some text");
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.