TextKitで行うテキスト装飾パターン/Text decoration pattern with TextKit

3e77f9dbec6a87756d1dbdddab283aee?s=47 Nulab Inc.
October 30, 2019

TextKitで行うテキスト装飾パターン/Text decoration pattern with TextKit

3e77f9dbec6a87756d1dbdddab283aee?s=128

Nulab Inc.

October 30, 2019
Tweet

Transcript

  1. 2.

    ϓϩϑΟʔϧ • ٢ాଠҰ࿠ @dataich • Swift/Scala • גࣜձࣾψʔϥϘॴଐ • WebαʔϏε

    TypetalkΛ։ൃɾӡ༻த • ΢ΠΠϨ 2 By Taichiro Yoshida (@dataich)
  2. 7.

    ࠓ೔͓࿩͢Δ͜ͱ • TextKitͰߦ͏ςΩετ૷০ύλʔϯ • TextKitͱ͸ • ඪ४Ͱఏڙ͞Ε͍ͯΔ૷০ • ຊ୊ •

    ඪ४Ͱఏڙ͞Ε͍ͯͳ͍૷০ • ࣮૷ύλʔϯ • ·ͱΊ 7 By Taichiro Yoshida (@dataich)
  3. 9.

    TextKitͱ͸ TextKit | Apple Developer Documentation • ςΩετͷϨΠΞ΢τΛίϯτϩʔϧ͢Δ༷ʑͳΫϥεͷू·Γ • NSAttributedString

    • NSTextStorage (NSMutableAttributedString) • NSLayoutManager • NSTextContainer • UILabelɺUITextViewͳͲΛ࢖͍ͬͯΕ͹ࣗવͱͦͷҰ෦Λ࢖͍ͬͯΔ 9 By Taichiro Yoshida (@dataich)
  4. 16.

    ྫ let text = """ ෱ԬͷiOSΤϯδχΞୡ͕ओ࠵͢Δɺ ϓϩάϥϛϯάݴޠ Swift ͱͦͷपลٕज़ͷษڧձͰ͢ɻ ൃలΛଓ͚Δ

    Swift ͱͦͷपลٕज़ͷಈ޲Λ௥͍ɺ ॳ৺ऀ/্ڃऀ/࿝एஉঁΛ໰Θͣɺ৘ใަ׵ͷ৔ͱͯ͠ ػೳ͢Δ͜ͱΛ໨తͱ͍ͯ͠·͢ɻ """ 16 By Taichiro Yoshida (@dataich)
  5. 18.

    NSAttributedString.Key .foregroundColor - จࣈ৭ let attributedString = NSMutableAttributedString(string: text) attributedString.setAttributes(

    [NSAttributedString.Key.foregroundColor : UIColor.blue], range: NSRange(location: 18, length: 15)) 18 By Taichiro Yoshida (@dataich)
  6. 20.

    NSAttributedString.Key .backgroundColor - എܠ৭ let attributedString = NSMutableAttributedString(string: text) attributedString.setAttributes(

    [NSAttributedString.Key.backgroundColor : UIColor.lightGray], range: NSRange(location: 18, length: 15)) 20 By Taichiro Yoshida (@dataich)
  7. 22.

    NSAttributedString.Key .font - ϑΥϯτ let attributedString = NSMutableAttributedString(string: text) attributedString.setAttributes(

    [NSAttributedString.Key.font : UIFont.systemFont(ofSize: 14)], range: NSRange(location: 0, length: text.count)) attributedString.setAttributes( [NSAttributedString.Key.font : UIFont.boldSystemFont(ofSize: 14)], range: NSRange(location: 18, length: 15)) 22 By Taichiro Yoshida (@dataich)
  8. 30.

    1. NSAttributedStringʹΧελϜଐੑΛ௥Ճ͢Δ struct InlineCodeSample { // 1. ΧελϜଐੑͷΩʔΛఆٛ static let

    key = NSAttributedString.Key(rawValue: "InlineCode") var attributedString: NSAttributedString { ... let attributedString = NSMutableAttributedString(string: text) // 2. ൣғΛࢦఆͯ͠ΧελϜଐੑΛઃఆ attributedString.setAttributes([Self.key : UIColor.lightGray], range: NSRange(location: 18, length: 23)) return attributedString } } 30 By Taichiro Yoshida (@dataich)
  9. 31.

    2. NSLayoutManagerΛܧঝͨ͠ΫϥεΛ࡞Δ class CustomLayoutManager: NSLayoutManager { //ɹϨΠΞ΢τʹؔΘΔॲཧΛ࣮૷͢Δ } ... let

    textStorage = NSTextStorage() let layoutManager = CustomLayoutManager() let textContainer = NSTextContainer() layoutManager.addTextContainer(textContainer) textStorage.addLayoutManager(layoutManager) textView = UITextView(frame: .zero, textContainer: textContainer) 31 By Taichiro Yoshida (@dataich)
  10. 32.

    3. CustomLayoutManagerͰඞཁͳඳըϝιουΛΦʔόʔϥΠυ ͢Δ class CustomLayoutManager: NSLayoutManager { // എܠͷඳըΛߦ͏ॲཧ override

    func drawBackground(forGlyphRange glyphsToShow: NSRange, at origin: CGPoint) { super.drawBackground(forGlyphRange: glyphsToShow, at: origin) drawInlineCode(forGlyphRange: glyphsToShow, at: origin) } func drawInlineCode(forGlyphRange glyphsToShow: NSRange, at origin: CGPoint) { // ΠϯϥΠϯίʔυʹؔΘΔॲཧΛ࣮૷͢Δ } } 32 By Taichiro Yoshida (@dataich)
  11. 33.

    4. ΧελϜଐੑΛ࣋ͭจࣈྻͷൣғΛ୳͢ func drawInlineCode(forGlyphRange glyphsToShow: NSRange, at origin: CGPoint) {

    let range = characterRange( forGlyphRange: glyphsToShow, actualGlyphRange: nil) textStorage?.enumerateAttribute( InlineCodeSample.key, in: range, options: []) { (color, range, _) in // ΧελϜଐੑInlineCodeʹؔΘΔॲཧΛ࣮૷͢Δ }) } 33 By Taichiro Yoshida (@dataich)
  12. 35.

    5. ΧελϜଐੑΛ࣋ͭจࣈྻͷάϦϑ͕දࣔ͞ΕΔCGRectΛऔಘ ͯ͠ඳըॲཧΛߦ͏ let glyphRange = self.glyphRange(forCharacterRange: range, actualCharacterRange: nil)

    self.enumerateEnclosingRects( forGlyphRange: glyphRange, withinSelectedGlyphRange: glyphRange, in: container) { (rect, _) in // άϦϑ͕ඳը͞Ε͍ͯΔCGRect͕औಘͰ͖ΔͷͰ // UIBezierPathͳͲΛ࢖ͬͯഎܠ΍ϘʔμʔΛඳը͢Δ } 35 By Taichiro Yoshida (@dataich)
  13. 38.

    enumerateLineFragmentsͰߦྖҬͷCGRectΛऔಘ self.enumerateLineFragments( forGlyphRange: glyphRange) { (rect, usedRect, textContainer, glyphRange, stop)

    in // άϦϑ͕ඳը͞Ε͍ͯΔߦͷCGRect͕औಘͰ͖ΔͷͰ // ෳ਺ߦͷߴ͞Λܭࢉ͢ΔͳͲ͢Δ } • enumerateEnclosingRects͸άϦϑ͕දࣔ͞Ε͍ͯΔ֤ྖҬͷCGRectΛྻ ڍ • enumerateLineFragments͸άϦϑ͕දࣔ͞Ε͍ͯΔߦྖҬͷCGRectΛྻڍ • boundingRect͸શͯͷάϦϑ͕ऩ·ΔྖҬͷCGRect1ͭ 38 By Taichiro Yoshida (@dataich)
  14. 42.

    ·ͱΊ • NSAttributedStringʹΧελϜଐੑΛ௥Ճ͢Δ • NSLayoutManagerΛܧঝͨ͠ΫϥεΛ࡞Δ • CustomLayoutManagerͰඞཁͳඳըϝιουΛΦʔόʔϥΠυ͢Δ • ΧελϜଐੑΛ࣋ͭจࣈྻͷൣғΛ୳͢ •

    ΧελϜଐੑΛ࣋ͭจࣈྻͷάϦϑ͕දࣔ͞ΕΔCGRectΛऔಘͯ͠ඳ ըॲཧΛߦ͏ • TextKitཧղ͢Δͱָ͍͠ʂ 42 By Taichiro Yoshida (@dataich)