• Stars
    star
    103
  • Rank 333,046 (Top 7 %)
  • Language
    Objective-C
  • License
    MIT License
  • Created over 7 years ago
  • Updated about 5 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Fix the line height problems of TextKit

Neat

Version License Platform

Neat is a tool solve the line height problems when using TextKit on iOS.

Line heights (or the visual line sapcings) displayed by TextKit vary on different lines when mixing different languages in one text. It looks very ungraceful and breaks the beauty of text layout. A common example is Chinese-English mixed layout, and even English-emoji mix cannot escape!! UILabel and UITextView handle this very well. Neat make TextKit views look exactly the same to UILabel.

Neat also remove the extra line spacing of last line when text is truncated to the maxNumberOfLines. It may, but not always, happen when lineSpacing is greater than zero. This function makes it very convenient to constrain the spaces between textView and other views.

ComponentKit could be fixed with Neat.

Install

Install via CocoaPods:

pod "Neat"

Usage

Basic Usages:

  1. Import Neat and call [UIFont patchMetrics]; once before textView layout. Recommend in didFinishLaunchingWithOption: or class load method.
  2. set the delegate of textView's layouManager to [NELineHeightFixer sharedInstance]. If the delegate is occupied, wraps it with NSLayoutManagerDelegateFixerWrapper.

Advanced:

Please read "How it works" first.

Neat contains 2 parts:

  • a patch for UIFont. UIFont+Patch
    • It alone solve the line spacing problems.
  • a implementation of NSLayoutManagerDelegate. NELineHeightFixer and NSLayoutManagerDelegateFixerWrapper
    • It alone solve the problem extra line spacing below last line.
    • it alone solve the line spacing problems with an small exception.

These 2 parts work together solve the problems above perfectly.

NOTE: The patch for UIFont effects globally since it swizzles the methods of UIFont. This may have potential conflict on other parts. Walk around: use second part alone. To solve the small expection, you could set the maximumLineHeight of attribtuedString to fixedLineHeightForFontSize:paragraphStyle: of NELineHeightFixer.

How it works

The nature of diffent line heights when mixing different languages is the different metrics of different fonts. When you use system default font, you get SFUIText. SF only have glyphs for English text. When encountered emoji, it fall down to AppleColorEmojiUI. SF and AppleColorEmojiUI have different metrics, i.e. lineHeight, descender and etc. The later have larger lineHeight. When a line contain an emoji character, layoutManger gives a larger rect to display this line, which led to a larger visual line spacing.

( This is same to English-Chinese mix. PingFang have small lineHeight, so pure Chinese lines have small line spacings. PingFang also have different descender, which effects baseLineOffset, making it more wired in a English-Chinese mixed line. )

Two ways to solve the problem:

  • make all fonts' metrics the same
    • by swizzling the method of UIFont and return SFUIText's value
  • manully set the line rects
    • by implementing method of NSLayoutManagerDelegate: layoutManager:shouldSetLineFragmentRect:lineFragmentUsedRect:baselineOffset:inTextContainer:forGlyphRange: and modify the rects and baseLineOffset.

Neat implements both ways, beacuse neither of these methods alone can solve it well. The first can't handle the extra line spacing below last line. The second alone could solve all two problems, with a exception that having a small additional space below last line when last line or the truncated part contains emoji.

License

Neat is available under the MIT license. See the LICENSE file for more info.

More Repositories

1

cocoapods-binary

integrate pods in form of prebuilt frameworks conveniently, reducing compile time
Ruby
1,304
star
2

cocoapods-static-swift-framework

A cocoapods plugin enables static framework for all pods
Ruby
253
star
3

ComponentSwift

Bring ComponentKit to Swift, A React-inspired view framework for iOS
Objective-C++
49
star
4

fucking-beijing-bus-api

北京实时公交 API
Swift
47
star
5

cocoapods-developing-folder

a branch of tools for who heavily use development pods
Ruby
30
star
6

Mappable

flexible JSON to Model converter, specially optimized for immutable properties
Swift
27
star
7

RunMario

iOS jailbreak tweak that allow playing SuperMarioRun on jailbreak device
Logos
25
star
8

sketch-engineer-friendly-text

Sketch plugin that make text layer's metric friendly to iOS engineer
JavaScript
24
star
9

alternate-icon-demo

demo for changing icon dynamically for iOS app
Swift
15
star
10

LazyWarningChecker

move "Treat Warnings as Errors" to commit time
Python
7
star
11

Literal

convenient initializers for CGPoint and etc..
Swift
6
star
12

SmashTheAddress

崩溃日志符号化python脚本,使用atosl工具
Python
3
star
13

courses

复刻自己的一个android课程表app
Objective-C
3
star
14

JustMyPassword

Jailbreak tweak. Allow you add new card in wallet while using 4-digit password
Logos
3
star
15

Sketch-iOS-text-solution

Swift
3
star
16

MathjaxZhihu

use Mathjax to render equations in Zhihu.com
JavaScript
2
star
17

LEPhotoCollectionView

CollectionView and cell for viewing images like Photo app
Objective-C
2
star
18

go-optional

optional type for golang
Go
2
star
19

Shell

Run shell commands fastly
Swift
2
star
20

HiThere

popup an image beside the cursor
Swift
2
star
21

go-either

An Either type for golang with generics
Go
1
star
22

Ring

One ring to rule them all
Shell
1
star