2016-11-17 1 views
0

텍스트 킷으로 고정 된 행 높이의 속성 문자열을 그릴 때 문자는 항상 선 조각의 맨 아래에 정렬됩니다. 크기가 다른 문자를 한 줄에 사용하는 것이 좋지만 여러 줄이있는 텍스트의 흐름이 손상됩니다. 기준선은 각 선에 대해 가장 큰 디 센더에 의해 결정됩니다.큰 줄 높이의 문자로 기준선을 텍스트 키트로 맞 춥니 다

이 정확한 문제를 조금 더 자세히 설명하고 해결책이 무엇인지 보여주는 Sketch의 사람들로부터 article이 발견되었지만 분명히 설명하지 못했습니다. 이 문제를 해결했습니다. bad: shifted baseline, good: baselines remain constant

큰 라인 높이 두 줄을 보여주는이 결과는 이상적인 거리가 멀다 : characters not optically aligned

코드 내가 사용 :

은 기본적으로 내가 원하는 것입니다

let smallFont = UIFont.systemFont(ofSize: 15) 
let bigFont = UIFont.systemFont(ofSize: 25) 
let paragraphStyle = NSMutableParagraphStyle() 
paragraphStyle.minimumLineHeight = 22 
paragraphStyle.maximumLineHeight = 22 
var attributes = [ 
    NSFontAttributeName: smallFont, 
    NSParagraphStyleAttributeName: paragraphStyle 
] 

let textStorage = NSTextStorage() 
let textContainer = NSTextContainer(size: CGSize(width: 250, height: 500)) 
let layoutManager = NSLayoutManager() 
textStorage.append(NSAttributedString(string: "It is a long established fact that a reader will be ", attributes:attributes)) 
attributes[NSFontAttributeName] = bigFont 
textStorage.append(NSAttributedString(string: "distracted", attributes:attributes)) 
attributes[NSFontAttributeName] = smallFont 
textStorage.append(NSAttributedString(string: " by the readable content of a page when looking at its layout.", attributes:attributes)) 

layoutManager.addTextContainer(textContainer) 
textStorage.addLayoutManager(layoutManager) 

let textView = UITextView(frame: self.view.bounds, textContainer:textContainer) 
view.addSubview(textView) 

답변

1

나는이 작업을 할 수 있었지만, 불행히도 iOS 8 및 macOS 10.10에 대한 지원을 중단해야했습니다. 당신이 NSLayoutManager 다음 위임 호출을 구현하는 경우

, 각 라인 조각에 대한 baselineOffset 수행 할 작업을 결정하는 얻을 다음 NSTextStorage가 생성 될 때

optional func layoutManager(_ layoutManager: NSLayoutManager, 
shouldSetLineFragmentRect lineFragmentRect: UnsafeMutablePointer<CGRect>, 
         lineFragmentUsedRect: UnsafeMutablePointer<CGRect>, 
          baselineOffset: UnsafeMutablePointer<CGFloat>, 
          in textContainer: NSTextContainer, 
        forGlyphRange glyphRange: NSRange) -> Bool 

이후의 각 변경, 내가 열거 사용 된 모든 글꼴, 기본 줄 높이 (NSLayoutManager.defaultLineHeightForFont())를 계산하고 가장 큰 줄 높이를 저장하십시오. 위에서 언급 한 델리게이트 메소드의 구현에서 제공된 라인 조각에 대한 NSParagraphStyle의 현재 라인 높이를 확인하고 그 값 내에서 폰트의 라인 높이를 정렬합니다. 베이스 라인이 글꼴의 ascenderdescender 사이에 있다는 지식으로베이스 라인 오프셋을 계산할 수 있습니다. baselineOffset 값을 baselineOffset.memory(newOffset)으로 업데이트하면 모든 것이 원하는대로 정렬됩니다.

참고 :이 계산을 통해 올바른 값을 사용하고 있는지 잘 모르겠으므로이 코드를 구현하는 데 사용되는 실제 코드에 대해서는 너무 자세하게 설명하지 않습니다. 가까운 장래에 전체 접근법을 시도하고 입증했을 때이를 업데이트 할 수 있습니다.

업데이트 : 조정 기준선의 구현. textContainer가 변경 될 때마다 가장 큰 선 높이와 가장 큰 디 센더를 다시 계산합니다. 그런 다음 기본적으로 레이아웃 관리자의 델리게이트 함수에서이 작업을 수행합니다.

var baseline: CGFloat = (lineFragmentRect.pointee.height - biggestLineHeight)/2 
baseline += biggestLineHeight 
baseline -= biggestDescender 
baseline = min(max(baseline, 0), lineFragmentRect.pointee.height) 
baselineOffset.pointee = floor(baseline) 
+0

세부 정보를 게시 할 수 있습니까? 나는 당신이 이것을 어떻게하는지 궁금합니다. – ctietze

+1

간단한 구현으로 업데이트되었습니다. – Pim

관련 문제