Dactyloidae/mobile/ios/Client/Extensions/UIViewExtensions.swift
2026-06-26 21:04:09 -07:00

94 lines
3.1 KiB
Swift

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
import Foundation
extension UIView {
/**
* Takes a screenshot of the view with the given size.
*/
func screenshot(_ size: CGSize, offset: CGPoint? = nil, quality: CGFloat = 1) -> UIImage? {
assert(0...1 ~= quality)
let offset = offset ?? CGPoint(x: 0, y: 0)
UIGraphicsBeginImageContextWithOptions(size, false, UIScreen.main.scale * quality)
drawHierarchy(in: CGRect(origin: offset, size: frame.size), afterScreenUpdates: false)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return image
}
/**
* Takes a screenshot of the view with the given aspect ratio.
* An aspect ratio of 0 means capture the entire view.
*/
func screenshot(_ aspectRatio: CGFloat = 0, offset: CGPoint? = nil, quality: CGFloat = 1) -> UIImage? {
assert(aspectRatio >= 0)
var size: CGSize
if aspectRatio > 0 {
size = CGSize()
let viewAspectRatio = frame.width / frame.height
if viewAspectRatio > aspectRatio {
size.height = frame.height
size.width = size.height * aspectRatio
} else {
size.width = frame.width
size.height = size.width / aspectRatio
}
} else {
size = frame.size
}
return screenshot(size, offset: offset, quality: quality)
}
/*
* Performs a deep copy of the view. Does not copy constraints.
*/
func clone() -> UIView {
let data = NSKeyedArchiver.archivedData(withRootObject: self)
return NSKeyedUnarchiver.unarchiveObject(with: data) as! UIView
}
/**
* rounds the requested corners of a view with the provided radius
*/
func addRoundedCorners(_ cornersToRound: UIRectCorner, cornerRadius: CGSize, color: UIColor) {
let rect = bounds
let maskPath = UIBezierPath(roundedRect: rect, byRoundingCorners: cornersToRound, cornerRadii: cornerRadius)
// Create the shape layer and set its path
let maskLayer = CAShapeLayer()
maskLayer.frame = rect
maskLayer.path = maskPath.cgPath
let roundedLayer = CALayer()
roundedLayer.backgroundColor = color.cgColor
roundedLayer.frame = rect
roundedLayer.mask = maskLayer
layer.insertSublayer(roundedLayer, at: 0)
backgroundColor = UIColor.clear
}
/**
This allows us to find the view in a current view hierarchy that is currently the first responder
*/
static func findSubViewWithFirstResponder(_ view: UIView) -> UIView? {
let subviews = view.subviews
if subviews.count == 0 {
return nil
}
for subview: UIView in subviews {
if subview.isFirstResponder {
return subview
}
return findSubViewWithFirstResponder(subview)
}
return nil
}
}