Skip to content

Instantly share code, notes, and snippets.

@shingohry
Last active September 9, 2020 05:56
Show Gist options
  • Save shingohry/bb3e58284edd448efc66868eb0c38f46 to your computer and use it in GitHub Desktop.
Save shingohry/bb3e58284edd448efc66868eb0c38f46 to your computer and use it in GitHub Desktop.
create Snapshot of entire SpreadsheetView (SpreadsheetView: https://github.com/kishikawakatsumi/SpreadsheetView)
class Snapshotter {
static func createSnapshot(spreadsheetView: SpreadsheetView) -> UIImage? {
guard let rootView = spreadsheetView.subviews[0] as? UIScrollView,
let overlayView = spreadsheetView.subviews[1] as? UIScrollView else { return nil }
let bounds = spreadsheetView.bounds
let contentSize = overlayView.contentSize
let contentOffset = rootView.contentOffset
let numberOfColumns = Int(contentSize.width / bounds.width)
let columnRemain = contentSize.width.truncatingRemainder(dividingBy: bounds.width)
let numberOfPagesForColumn = numberOfColumns + (columnRemain > 0 ? 1 : 0)
let numberOfRows = Int(contentSize.height / bounds.height)
let rowRemain = contentSize.height.truncatingRemainder(dividingBy: bounds.height)
let numberOfPagesForRow = numberOfRows + (rowRemain > 0 ? 1 : 0)
rootView.contentOffset = .zero
let lastColumn = numberOfPagesForColumn - 1
let lastRow = numberOfPagesForRow - 1
var elements = [Element]()
for column in 0..<numberOfPagesForColumn {
for row in 0..<numberOfPagesForRow {
let offset: CGPoint
if column == lastColumn && row == lastRow {
offset = CGPoint(x: contentSize.width - bounds.width,
y: contentSize.height - bounds.height)
} else if column == lastColumn {
offset = CGPoint(x: contentSize.width - bounds.width,
y: bounds.height * CGFloat(row))
} else if row == lastRow {
offset = CGPoint(x: bounds.width * CGFloat(column),
y: contentSize.height - bounds.height)
} else {
offset = CGPoint(x: bounds.width * CGFloat(column),
y: bounds.height * CGFloat(row))
}
spreadsheetView.setContentOffset(offset, animated: false)
guard let image = spreadsheetView.snapshot else { continue }
let element = Element(rect: CGRect(origin: offset, size: bounds.size), image: image)
elements.append(element)
}
}
// ContentOffsetをもとに戻す
spreadsheetView.setContentOffset(contentOffset, animated: false)
let image = composeImage(size: contentSize,
elements: elements)
return image
}
}
private extension Snapshotter {
struct Element {
let rect: CGRect
let image: UIImage
}
static func composeImage(size: CGSize, elements: [Element]) -> UIImage? {
defer {
// end context
UIGraphicsEndImageContext()
}
UIGraphicsBeginImageContextWithOptions(size, false, 0.0)
// x座標が大きい方から描画されるように並び替える
let sortedElements = elements.sorted { $0.rect.origin.x > $1.rect.origin.x }
sortedElements.forEach { element in
element.image.draw(in: element.rect)
}
return UIGraphicsGetImageFromCurrentImageContext()
}
}
private extension UIView {
var snapshot: UIImage? {
defer {
// end context
UIGraphicsEndImageContext()
}
let size = bounds.size
UIGraphicsBeginImageContextWithOptions(size, false, 0.0)
guard let context = UIGraphicsGetCurrentContext() else { return nil }
layer.render(in: context)
let image = UIGraphicsGetImageFromCurrentImageContext()
return image
}
}
@SexyBeast007
Copy link

This seems to dequeue the frozen header bar when printing or saving image. How do i not dequeue header bar?

@shingohry
Copy link
Author

It's a code I wrote a long time ago, so I can't answer it immediately.
I'm sorry.
I will check when I have time.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment