Last active
March 15, 2017 00:47
-
-
Save justdoit0823/15aa68be7512da771d0f4fbaa1881bd9 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// ViewController.swift | |
// SlideView | |
// | |
// Created by 余森彬 on 2017/3/10. | |
// Copyright © 2017年 余森彬. All rights reserved. | |
// | |
import CoreGraphics | |
import CoreText | |
import Foundation | |
import UIKit | |
class BackgroundAttributeView: UIView { | |
var text:NSAttributedString = { | |
var att = [NSFontAttributeName:UIFont(name:"Helvetica", size:20)!] | |
var text = NSMutableAttributedString(string: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis ullamco", attributes:att) | |
text.append(NSAttributedString(string: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum", attributes: ["kBackgroundAttribute":UIColor.cyan])) | |
text.append(NSAttributedString(string: " Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation", attributes:att)) | |
return text | |
}() | |
override func draw(_ rect: CGRect) { | |
super.draw(rect) | |
var frameSetter = CTFramesetterCreateWithAttributedString(text) | |
var framePath = CGMutablePath() | |
framePath.addRect(self.bounds) | |
var ctFrame = CTFramesetterCreateFrame(frameSetter, CFRangeMake(0, 0), framePath, nil) | |
var frameRange = CTFrameGetVisibleStringRange(ctFrame) | |
var ctx = UIGraphicsGetCurrentContext() | |
ctx?.saveGState() | |
ctx?.textMatrix = CGAffineTransform.identity | |
ctx?.translateBy(x: 0, y: bounds.height) | |
ctx?.scaleBy(x: 1.0, y: -1.0) | |
var lines:NSArray = CTFrameGetLines(ctFrame) | |
var lineOrigins:[CGPoint] = [CGPoint](repeating: CGPoint.zero, count:lines.count) | |
CTFrameGetLineOrigins(ctFrame, CFRangeMake(0, 0), &lineOrigins) | |
var currentLineHeight:CGFloat = 0 | |
var lineHeight:CGFloat = 0 | |
for (lineIndex, line) in lines.enumerated() { | |
let lineOrigin = lineOrigins[lineIndex] | |
var runs:NSArray = CTLineGetGlyphRuns(line as! CTLine) | |
for run:CTRun in runs as! [CTRun] { | |
let stringRange = CTRunGetStringRange(run) | |
var ascent:CGFloat = 0 | |
var descent:CGFloat = 0 | |
var leading:CGFloat = 0 | |
let typographicBounds = CTRunGetTypographicBounds(run, CFRangeMake(0, 0), &ascent, &descent, &leading) | |
var xOffset:CGFloat = CTLineGetOffsetForStringIndex(line as! CTLine, stringRange.location, nil) | |
ctx?.textPosition = CGPoint(x: lineOrigin.x, y: lineOrigin.y + descent) | |
var currentLineHeight = ascent + descent + leading | |
if currentLineHeight > lineHeight { | |
lineHeight = currentLineHeight | |
} | |
var runBounds = CGRect(x: lineOrigin.x + xOffset, y: lineOrigin.y, width: CGFloat(typographicBounds), height: (ascent + descent)) | |
var attributes:NSDictionary = CTRunGetAttributes(run) | |
var maybeColor = attributes.value(forKey: "kBackgroundAttribute") as! UIColor? | |
if let color = maybeColor { | |
let path = UIBezierPath(roundedRect: runBounds, cornerRadius: 3) | |
color.setFill() | |
path.fill() | |
} | |
CTRunDraw(run, ctx!, CFRangeMake(0, 0)) | |
} | |
} | |
ctx?.restoreGState() | |
} | |
} | |
class ViewController: UIViewController { | |
@IBOutlet weak var textView: UITextView! | |
@IBOutlet weak var webView: UIWebView! | |
var leftSubView: UIView! | |
var rightSubView: UIView! | |
@IBAction func showView(_ sender: Any) { | |
let parentFrame = self.view.frame | |
let leftframe = CGRect(x: 0, y: 0, width: 0, height: parentFrame.height) | |
let rightframe = CGRect(x: parentFrame.width * 0.8, y: 0, width: parentFrame.width * 0.2, height: parentFrame.height) | |
let slideView = UIView(frame: leftframe) | |
let rightView = UIView(frame: rightframe) | |
let singleFingerTap = UITapGestureRecognizer(target: self, action: #selector(self.closeSlide)) | |
rightView.addGestureRecognizer(singleFingerTap) | |
slideView.backgroundColor = UIColor(red: 2, green: 2, blue: 2, alpha: 0.8) | |
slideView.layer.shadowOpacity = 0.8 | |
rightView.backgroundColor = UIColor(red: 1, green: 1, blue: 1, alpha: 0.95) | |
self.view.addSubview(slideView) | |
UIView.transition(with: slideView, duration: 1.0, options: UIViewAnimationOptions.curveEaseInOut, animations: ({slideView.frame = CGRect(x: 0, y: 0, width: parentFrame.width * 0.8, height: parentFrame.height)})) | |
self.view.insertSubview(rightView, belowSubview: slideView) | |
UIView.transition(with: slideView, duration: 0.5, options: UIViewAnimationOptions.curveEaseInOut, animations: ({rightView.alpha = 1})) | |
self.leftSubView = slideView | |
self.rightSubView = rightView | |
//NSAttributedString | |
NSHTMLTextDocumentType | |
//NSParagraphStyle | |
} | |
func loadHtmlText() { | |
// let html_text = "<html><head><style type='text/css'>div{background-color:#00FFFF;width:150px;height:150px;overflow: auto}</style></head><body> | |
// <p>如果元素中的内容超出了给定的宽度和高度属性,overflow 属性可以确定是否显示滚动条等行为。</p> | |
// | |
// <div> | |
// 这个属性定义溢出元素内容区的内容会如何处理。如果值为 scroll,不论是否需要,用户代理都会提供一种滚动机制。因此,有可能即使元素框中可以放下所有内容也会出现滚动条。默认值是 visible。 | |
// </div> | |
// </body> | |
// | |
// </html>" | |
let html_text = "<html><meta charset='utf-8'>\n<head>\n<style type='text/css'>\ndiv {\nbackground-color:#00FFFF;\nwidth:10em;\nheight:10em;\ntext-overflow: scroll\n; margin: 10ex;}\n</style>\n</head>\n\n<body>\n<p>如果元素中的内容超出了给定的宽度和高度属性,overflow 属性可以确定是否显示滚动条等行为。</p>\n\n<div>\n这个属性定义溢出元素内容区的内容会如何处理。如果值为 scroll,不论是否需要,用户代理都会提供一种滚动机制。因此,有可能即使元素框中可以放下所有内容也会出现滚动条。默认值是 visible。\n</div>\n</body>\n\n</html>" | |
let html_pre_text = "<pre class=\"PROGRAMLISTING\" nodeIndex=\"76\">\nmytable.arraycolumn[4]xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\nmytable.two_d_column[17][34]\n$1[10:42]\n(arrayfunction(a,b))[42]\n</pre>" | |
let paraStyle = NSMutableParagraphStyle() | |
paraStyle.lineSpacing = 10 | |
paraStyle.paragraphSpacing = 5 | |
let shadow = NSShadow() | |
shadow.shadowBlurRadius = 5 | |
shadow.shadowColor = UIColor.brown | |
shadow.shadowOffset = CGSize(width: 10, height: 20) | |
do{ | |
let attrText = try NSMutableAttributedString(data: Data(Array(html_text.utf8)), options: [NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType], documentAttributes: nil) | |
// attrText.setAttributes([NSShadowAttributeName: shadow], range: NSRange(location: 0, length: attrText.length)) | |
self.textView.attributedText = attrText | |
} | |
catch { | |
print("exception") | |
} | |
} | |
override func viewDidLoad() { | |
super.viewDidLoad() | |
// Do any additional setup after loading the view, typically from a nib. | |
//self.loadHtmlText() | |
let html_str = "<pre class=\"PROGRAMLISTING\" nodeIndex=\"76\">\nmytable.arraycolumn[4]xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\nmytable.two_d_column[17][34]\n$1[10:42]\n(arrayfunction(a,b))[42]\n</pre>" | |
let content_str = "" | |
let backView = BackgroundAttributeView(frame: CGRect(x: 0, y: 0, width: self.view.frame.width, height: self.view.frame.height)) | |
self.view.addSubview(backView) | |
self.webView.loadHTMLString(content_str, baseURL: nil) | |
} | |
override func didReceiveMemoryWarning() { | |
super.didReceiveMemoryWarning() | |
// Dispose of any resources that can be recreated. | |
} | |
func closeSlide(_ sender: UITapGestureRecognizer) { | |
//self.leftSubView?.isHidden = true | |
let parentFrame = self.view.frame | |
UIView.transition(with: self.leftSubView, duration: 1.0, options: UIViewAnimationOptions.curveEaseInOut, animations: ({self.leftSubView.frame = CGRect(x: 0, y: 0, width: 0, height: parentFrame.height)})) | |
UIView.transition(with: self.rightSubView, duration: 0.5, options: UIViewAnimationOptions.curveEaseInOut, animations: ({self.rightSubView.alpha = 0})) | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment