[英]How can I add a badge to a leading navigationBarItems in SwiftUI and iOS 14?
[英]iOS 13: How can I tweak the leading / descend / line height of a custom font in UIKit / SwiftUI
我正在使用自定義字體,並且渲染以某種方式搞砸了行高,這可能是由於錯誤配置的descent
或leading
(?),因此 g 和 j 在渲染文本的最后一行被截斷。 我認為這可能是這種特定字體的問題,因為 Sketch 也暴露了相關字體的類似問題,但我覺得我對排版測量或字體的了解還不夠。 我發現Typographic Concepts上的這個 Apple 文檔頁面非常有見地。
我使用 FontLab 的測試版本查看了字體本身,順便說一句,這是我第一次使用的 - 所以我幾乎不知道我在看什么。 看起來 g 確實低於配置的descent
,這似乎是最后一行。 (?)(參見: FontLab 中的字符視圖,顯示 g 的下降部分)
通過lineSpacing
我可以調整線條本身之間的距離以在前幾行中解決這個問題。 我知道iOS的14會帶來一個辦法修改leading
一個的Text
中SwiftUI。 但我需要針對 iOS 13,所以這無濟於事。
我也嘗試過 SwiftUI 的Text
,一個普通的UILabel.text
和UILabel.attributedText
,帶有自定義的段落樣式,但我在那里調整的任何東西似乎都沒有緩解這個問題。 視圖甚至沒有剪輯。 只是向框架添加填充根本沒有幫助。 它增加了距離,但 g 和 j 仍然被切斷。
我能做什么? 當最后一行有 ag 和 j 時,繼承UILabel
並覆蓋intrinsicContentSize
以添加一些額外的空間? 感覺 a) 臟 b) 考慮到填充沒有幫助,它可能無法解決問題?
字體本身是這里的問題嗎? 我可以以某種方式修補字體而不會使它變得更糟嗎?
當我使用較低級別的 API 時,有什么方法可以修改字體的前導或下降高度? 似乎我可以轉到 CoreText,因為CTFontCreateCopyWithAttributes(_:_:_:_:)
是候選對象,如果我可以通過屬性修改前導、行距或下降? 可以或猴子補丁/ swizzle 東西而不會射中自己的膝蓋嗎? 我應該
向雷達
提交反饋嗎?
您需要使用NSAttributedString
而不是 String 來控制 UILabel 的行距。 這是示例代碼
let style = NSMutableParagraphStyle()
style.lineSpacing = 20
let string = NSMutableAttributedString(string: "The quick brown fox jumps over the lazy dog, The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog")
string.addAttribute(.paragraphStyle, value: style, range: NSMakeRange(0, string.length))
let label = UILabel(frame: CGRect(x: 20, y: 100, width: 300, height: 500))
label.attributedText = string
label.numberOfLines = 0
self.view.addSubview(label)
輸出
我知道您在問什么,因為我遇到了與自定義字體相同的問題。 我將提供兩種解決方案。 在我自己的項目中,我按照您的建議覆蓋了 internalContentSize 並為高度和寬度添加了一個填充乘數。 在我的例子中,字體是面向用戶的,所以我有一個包含所有相關信息的結構。 僅供參考 Chalkduster 在系統和剪輯中。 我也相信這都是字體文件本身造成的。
解決方案 1:示例:
struct UserFont{
var name : String
var displayName : String
var widthMultiplier : CGFloat
var heightMultiplier : CGFloat
}
然后在我的 UILabel 中,我將其子類化為使用這兩個指標
@IBDesignable
class MultiplierUILabel: UILabel {
@IBInspectable var widthPaddingMultiplier : CGFloat = 1
@IBInspectable var heightPaddingMultiplier : CGFloat = 1
override var intrinsicContentSize: CGSize{
return CGSize(width: super.intrinsicContentSize.width * widthPaddingMultiplier, height: super.intrinsicContentSize.height * heightPaddingMultiplier)
}
}
這對我來說是最簡單的實現,因為我找到了相應的字體和乘數比例。
解決方案2:
您可以通過測量字形邊界並調整原點 y 來使繪制發生得稍高一些。 例如,這修復了系統中包含的 Chalkduster 字體的剪輯。
@IBDesignable
class PaddingUILabel: UILabel {
override func drawText(in rect:CGRect) {
//hello
guard let labelText = text else { return super.drawText(in: rect) }
//just some breathing room
let info = boundsForAttrString(str: labelText, font: self.font!, kern: .leastNormalMagnitude)
let glyph = info.glyph
var newRect = rect
let glyphPadding = -(glyph.origin.y)
if glyphPadding - info.descent > 1 && info.descent != 0{
newRect.origin.y -= glyphPadding/2
}else{
if info.descent != 0{
newRect.origin.y += (info.descent - glyphPadding)/2
}
}
super.drawText(in: newRect)
}
func boundsForAttrString(str:String,font:UIFont,kern:CGFloat)->(glyph:CGRect,descent:CGFloat){
let attr = NSAttributedString(string: str, attributes: [.font:font,.kern:kern])
let line = CTLineCreateWithAttributedString(attr)
var ascent : CGFloat = 0
var descent : CGFloat = 0
var leading : CGFloat = 0
CTLineGetTypographicBounds(line, &ascent, &descent, &leading)
let glyph = CTLineGetBoundsWithOptions(line, .useGlyphPathBounds).integral
return (glyph,leading != 0 ? descent : 0)
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.