ios - Align baselines with characters in large line heights with Text Kit -


when draw attributed string fixed line height text kit, characters aligned bottom of line fragment. while make sense on 1 line characters varying in size, breaks flow of text multiple lines. baselines appear decided largest descender each line.

i've found article people behind sketch explaining exact problem in bit more detail , showing solution does, not explaining how achieved this.

this want basically: bad: shifted baseline, good: baselines remain constant

when showing 2 lines large line height, result far ideal: characters not optically aligned

the code i'm using:

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 long established fact reader ", attributes:attributes)) attributes[nsfontattributename] = bigfont textstorage.append(nsattributedstring(string: "distracted", attributes:attributes)) attributes[nsfontattributename] = smallfont textstorage.append(nsattributedstring(string: " readable content of page when looking @ layout.", attributes:attributes))  layoutmanager.addtextcontainer(textcontainer) textstorage.addlayoutmanager(layoutmanager)  let textview = uitextview(frame: self.view.bounds, textcontainer:textcontainer) view.addsubview(textview) 

i managed working, had drop support ios 8 , macos 10.10 unfortunately.

if implement following delegate call of nslayoutmanager, decide baselineoffset each line fragment:

optional func layoutmanager(_ layoutmanager: nslayoutmanager,   shouldsetlinefragmentrect linefragmentrect: unsafemutablepointer<cgrect>,                         linefragmentusedrect: unsafemutablepointer<cgrect>,                               baselineoffset: unsafemutablepointer<cgfloat>,                             in textcontainer: nstextcontainer,                     forglyphrange glyphrange: nsrange) -> bool 

when nstextstorage created , each subsequent change, enumerate used font, calculate it's default line height (nslayoutmanager.defaultlineheightforfont()) , store biggest line height. in implementation of above mentioned delegate method check current line height of nsparagraphstyle provided line fragment , align font's line height within value. there baseline offset can calculated knowledge baseline sits between font's ascender , descender. update baselineoffset value baselineoffset.memory(newoffset) , should aligned you'd like.

note: i'm not going in detail actual code used implement because i'm not sure i'm using right values throughout these calculations. might update in near future when whole approach tried , proven.

update: implementation of adjusting baseline. every time textcontainer changes recalculate biggest line height , biggest descender. in layout manager's delegate function:

var baseline: cgfloat = (linefragmentrect.pointee.height - biggestlineheight) / 2 baseline += biggestlineheight baseline -= biggestdescender baseline = min(max(baseline, 0), linefragmentrect.pointee.height) baselineoffset.pointee = floor(baseline) 

Comments

Popular posts from this blog

javascript - Uncaught FirebaseError: Messaging: This method is available in a Window context -

c# - How to clear picker if It is selected in xamarin forms? -

angular - File Name and Extension not respected when sent from .NET Web API to Angular2 App -