// // UIView+Extension.swift // QuickSearchLocation // // Created by mac on 2024/4/10. // import Foundation import UIKit import Toast_Swift // MARK: - 屏幕尺寸常用的常量 public extension UIView { // MARK: 1.1、是否是缺口屏幕(刘海屏)或者灵动岛的屏幕 // 是否是缺口屏幕(刘海屏)或者灵动岛的屏幕 var qsl_isIPhoneNotch: Bool { if #available(iOS 11.0, *) { if let window = UIApplication.keyWindow { return window.safeAreaInsets.bottom > 0 } else { return false } } else { return UIApplication.shared.statusBarFrame.height > 20 } } // MARK: 2.1、屏幕的宽 /// 屏幕的宽 var qsl_kScreenW: CGFloat { return UIScreen.main.bounds.width } // MARK: 2.2、屏幕的高 /// 屏幕的高 var qsl_kScreenH: CGFloat { return UIScreen.main.bounds.height } // MARK: 2.3、获取statusBar的高度 /// 获取statusBar的高度 var qsl_kStatusBarFrameH: CGFloat { if #available(iOS 13.0, *) { let window: UIWindow? = UIApplication.shared.windows.first let statusBarHeight = (window?.windowScene?.statusBarManager?.statusBarFrame.height) ?? 0 return statusBarHeight } else { // 防止界面没有出来获取为0的情况 return UIApplication.shared.statusBarFrame.height > 0 ? UIApplication.shared.statusBarFrame.height : 44 } } // MARK: 2.4、获取导航栏的高度 /// 获取导航栏的高度 var qsl_kNavFrameH: CGFloat { return 44 + qsl_kStatusBarFrameH } // MARK: 2.5、屏幕底部Tabbar高度 /// 屏幕底部Tabbar高度 var qsl_kTabbarFrameH: CGFloat { return qsl_isIPhoneNotch ? 83 : 49 } // MARK: 2.6、屏幕底部刘海高度 /// 屏幕底部刘海高度 var qsl_kTabbarBottom: CGFloat { return qsl_isIPhoneNotch ? 34 : 0 } // MARK: 2.7、屏幕比例 /// 屏幕比例 var qsl_kPixel: CGFloat { return 1.0 / UIScreen.main.scale } var qsl_kScale: CGFloat { return qsl_kScreenW / CGFloat(375.0) } } // MARK: - UIView 有关 Frame 的扩展 public extension UIView { // MARK: 3.1、x 的位置 /// x 的位置 var qsl_x: CGFloat { get { return frame.origin.x } set(newValue) { var tempFrame: CGRect = frame tempFrame.origin.x = newValue frame = tempFrame } } // MARK: 3.2、y 的位置 /// y 的位置 var qsl_y: CGFloat { get { return frame.origin.y } set(newValue) { var tempFrame: CGRect = frame tempFrame.origin.y = newValue frame = tempFrame } } // MARK: 3.3、height: 视图的高度 /// height: 视图的高度 var qsl_height: CGFloat { get { return frame.size.height } set(newValue) { var tempFrame: CGRect = frame tempFrame.size.height = newValue frame = tempFrame } } // MARK: 3.4、width: 视图的宽度 /// width: 视图的宽度 var qsl_width: CGFloat { get { return frame.size.width } set(newValue) { var tempFrame: CGRect = frame tempFrame.size.width = newValue frame = tempFrame } } // MARK: 3.5、size: 视图的zize /// size: 视图的zize var qsl_size: CGSize { get { return frame.size } set(newValue) { var tempFrame: CGRect = frame tempFrame.size = newValue frame = tempFrame } } // MARK: 3.6、centerX: 视图的X中间位置 /// centerX: 视图的X中间位置 var qsl_centerX: CGFloat { get { return center.x } set(newValue) { var tempCenter: CGPoint = center tempCenter.x = newValue center = tempCenter } } // MARK: 3.7、centerY: 视图的Y中间位置 /// centerY: 视图Y的中间位置 var qsl_centerY: CGFloat { get { return center.y } set(newValue) { var tempCenter: CGPoint = center tempCenter.y = newValue center = tempCenter } } // MARK: 3.9、top 上端横坐标(y) /// top 上端横坐标(y) var qsl_top: CGFloat { get { return frame.origin.y } set(newValue) { var tempFrame: CGRect = frame tempFrame.origin.y = newValue frame = tempFrame } } // MARK: 3.10、left 左端横坐标(x) /// left 左端横坐标(x) var qsl_left: CGFloat { get { return frame.origin.x } set(newValue) { var tempFrame: CGRect = frame tempFrame.origin.x = newValue frame = tempFrame } } // MARK: 3.11、bottom 底端纵坐标 (y + height) /// bottom 底端纵坐标 (y + height) var qsl_bottom: CGFloat { get { return frame.origin.y + frame.size.height } set(newValue) { frame.origin.y = newValue - frame.size.height } } // MARK: 3.12、right 底端纵坐标 (x + width) /// right 底端纵坐标 (x + width) var qsl_right: CGFloat { get { return frame.origin.x + frame.size.width } set(newValue) { frame.origin.x = newValue - frame.size.width } } // MARK: 3.13、origin 点 /// origin 点 var qsl_origin: CGPoint { get { return frame.origin } set(newValue) { var tempOrigin: CGPoint = frame.origin tempOrigin = newValue frame.origin = tempOrigin } } } // MARK: - 关于UIView的 圆角、阴影、边框、虚线 的设置 public extension UIView { // MARK: 5.1、添加圆角 /// 添加圆角 /// - Parameters: /// - radius: 圆角的大小 func addRadius(radius:CGFloat) { self.layer.cornerRadius = radius self.clipsToBounds = true } // MARK: 5.1、添加圆角 /// 添加圆角 /// - Parameters: /// - conrners: 具体哪个圆角 /// - radius: 圆角的大小 func addCorner(conrners: UIRectCorner , radius: CGFloat) { let maskPath = UIBezierPath(roundedRect: self.bounds, byRoundingCorners: conrners, cornerRadii: CGSize(width: radius, height: radius)) let maskLayer = CAShapeLayer() maskLayer.frame = self.bounds maskLayer.path = maskPath.cgPath self.layer.mask = maskLayer } // MARK: 5.2、添加圆角和边框 /// 添加圆角和边框 /// - Parameters: /// - conrners: 具体哪个圆角 /// - radius: 圆角的大小 /// - borderWidth: 边框的宽度 /// - borderColor: 边框的颜色 func addCorner(conrners: UIRectCorner , radius: CGFloat, borderWidth: CGFloat, borderColor: UIColor) { let maskPath = UIBezierPath(roundedRect: self.bounds, byRoundingCorners: conrners, cornerRadii: CGSize(width: radius, height: radius)) let maskLayer = CAShapeLayer() maskLayer.frame = self.bounds maskLayer.path = maskPath.cgPath self.layer.mask = maskLayer // Add border let borderLayer = CAShapeLayer() borderLayer.path = maskLayer.path borderLayer.fillColor = UIColor.clear.cgColor borderLayer.strokeColor = borderColor.cgColor borderLayer.lineWidth = borderWidth borderLayer.frame = self.bounds self.layer.addSublayer(borderLayer) } // MARK: 5.3、给继承于view的类添加阴影 /// 给继承于view的类添加阴影 /// - Parameters: /// - shadowColor: 阴影的颜色 /// - shadowOffset: 阴影的偏移度:CGSizeMake(X[正的右偏移,负的左偏移], Y[正的下偏移,负的上偏移]) /// - shadowOpacity: 阴影的透明度 /// - shadowRadius: 阴影半径,默认 3 func addShadow(shadowColor: UIColor, shadowOffset: CGSize, shadowOpacity: Float, shadowRadius: CGFloat = 3) { // 设置阴影颜色 layer.shadowColor = shadowColor.cgColor // 设置透明度 layer.shadowOpacity = shadowOpacity // 设置阴影半径 layer.shadowRadius = shadowRadius // 设置阴影偏移量 layer.shadowOffset = shadowOffset } // MARK: 5.4、添加阴影和圆角并存 /// 添加阴影和圆角并存 /// /// - Parameter superview: 父视图 /// - Parameter conrners: 具体哪个圆角 /// - Parameter radius: 圆角大小 /// - Parameter shadowColor: 阴影的颜色 /// - Parameter shadowOffset: 阴影的偏移度:CGSizeMake(X[正的右偏移,负的左偏移], Y[正的下偏移,负的上偏移]) /// - Parameter shadowOpacity: 阴影的透明度 /// - Parameter shadowRadius: 阴影半径,默认 3 /// /// - Note1: 如果在异步布局(如:SnapKit布局)中使用,要在布局后先调用 layoutIfNeeded,再使用该方法 /// - Note2: 如果在添加阴影的视图被移除,底部插入的父视图的layer是不会被移除的⚠️ func addCornerAndShadow(superview: UIView, conrners: UIRectCorner , radius: CGFloat = 3, shadowColor: UIColor, shadowOffset: CGSize, shadowOpacity: Float, shadowRadius: CGFloat = 3) { let maskPath = UIBezierPath(roundedRect: self.bounds, byRoundingCorners: conrners, cornerRadii: CGSize(width: radius, height: radius)) let maskLayer = CAShapeLayer() maskLayer.frame = self.bounds maskLayer.path = maskPath.cgPath self.layer.mask = maskLayer let subLayer = CALayer() let fixframe = self.frame subLayer.frame = fixframe subLayer.cornerRadius = radius subLayer.backgroundColor = shadowColor.cgColor subLayer.masksToBounds = false // shadowColor阴影颜色 subLayer.shadowColor = shadowColor.cgColor // shadowOffset阴影偏移,x向右偏移3,y向下偏移2,默认(0, -3),这个跟shadowRadius配合使用 subLayer.shadowOffset = shadowOffset // 阴影透明度,默认0 subLayer.shadowOpacity = shadowOpacity // 阴影半径,默认3 subLayer.shadowRadius = shadowRadius subLayer.shadowPath = maskPath.cgPath superview.layer.insertSublayer(subLayer, below: self.layer) } // MARK: 5.5、通过贝塞尔曲线View添加阴影和圆角 /// 通过贝塞尔曲线View添加阴影和圆角 /// /// - Parameter conrners: 具体哪个圆角(暂时只支持:allCorners) /// - Parameter radius: 圆角大小 /// - Parameter shadowColor: 阴影的颜色 /// - Parameter shadowOffset: 阴影的偏移度:CGSizeMake(X[正的右偏移,负的左偏移], Y[正的下偏移,负的上偏移]) /// - Parameter shadowOpacity: 阴影的透明度 /// - Parameter shadowRadius: 阴影半径,默认 3 /// /// - Note: 提示:如果在异步布局(如:SnapKit布局)中使用,要在布局后先调用 layoutIfNeeded,再使用该方法或者在override func layoutSublayers(of layer: CALayer) {} 里面调用,也要使用 layoutIfNeeded func addViewCornerAndShadow(conrners: UIRectCorner , radius: CGFloat = 3, shadowColor: UIColor, shadowOffset: CGSize, shadowOpacity: Float, shadowRadius: CGFloat = 3) { // 切圆角 layer.shadowColor = shadowColor.cgColor layer.shadowOffset = shadowOffset layer.shadowOpacity = shadowOpacity layer.shadowRadius = shadowRadius layer.cornerRadius = radius // 路径阴影 let path = UIBezierPath.init(roundedRect: bounds, byRoundingCorners: conrners, cornerRadii: CGSize.init(width: radius, height: radius)) layer.shadowPath = path.cgPath } // MARK: 5.6、添加边框 /// 添加边框 /// - Parameters: /// - width: 边框宽度 /// - color: 边框颜色 func addBorder(borderWidth: CGFloat, borderColor: UIColor) { layer.borderWidth = borderWidth layer.borderColor = borderColor.cgColor layer.masksToBounds = true } // MARK: 5.7、毛玻璃效果 /// 毛玻璃效果 /// - Parameters: /// - alpha: 可设置模糊的程度(0-1),越大模糊程度越大 /// - size: 毛玻璃的size /// - style: 模糊效果 func effectViewWithAlpha(alpha: CGFloat = 1.0, size: CGSize? = nil, style: UIBlurEffect.Style = .light) { // 模糊视图的大小 var visualEffectViewSize = CGSize(width: 0, height: 0) if let weakSize = size { visualEffectViewSize = weakSize } else { visualEffectViewSize = self.qsl_size } let visualEffectView = UIVisualEffectView.visualEffectView(size: visualEffectViewSize, alpha: alpha, style: style, isAddVibrancy: false) self.addSubview(visualEffectView) } // 设置渐变颜色 func gradientBackgroundColor(color1: UIColor, color2: UIColor, width: CGFloat, height: CGFloat, direction: ImageGradientDirection) { if let image = UIImage.gradient([color1, color2], size: CGSize(width: width, height: height), locations: [0, 1], direction: direction) { self.backgroundColor = UIColor(patternImage: image) } } } extension UIView { func addFourCornerAndBorder(topLeft: CGFloat, topRight: CGFloat, bottomLeft: CGFloat, bottomRight: CGFloat, borderWidth: CGFloat, borderColor: UIColor){ let cornerRadii = UIView.CornerRadii.init(topLeft: topLeft, topRight: topRight, bottomLeft: bottomLeft, bottomRight: bottomRight) let path = createPathWithRoundedRect(bounds: self.bounds, cornerRadii:cornerRadii) let shapLayer = CAShapeLayer() shapLayer.frame = self.bounds shapLayer.path = path self.layer.mask = shapLayer // Add border let borderLayer = CAShapeLayer() borderLayer.path = shapLayer.path borderLayer.fillColor = UIColor.clear.cgColor borderLayer.strokeColor = borderColor.cgColor borderLayer.lineWidth = borderWidth borderLayer.frame = self.bounds self.layer.insertSublayer(borderLayer, at: 0) } //添加4个不同大小的圆角 func addFourCorner(topLeft: CGFloat, topRight: CGFloat, bottomLeft: CGFloat, bottomRight: CGFloat){ let cornerRadii = UIView.CornerRadii.init(topLeft: topLeft, topRight: topRight, bottomLeft: bottomLeft, bottomRight: bottomRight) let path = createPathWithRoundedRect(bounds: self.bounds, cornerRadii:cornerRadii) let shapLayer = CAShapeLayer() shapLayer.frame = self.bounds shapLayer.path = path self.layer.mask = shapLayer } //各圆角大小 struct CornerRadii { var topLeft :CGFloat = 0 var topRight :CGFloat = 0 var bottomLeft :CGFloat = 0 var bottomRight :CGFloat = 0 } //切圆角函数绘制线条 func createPathWithRoundedRect (bounds:CGRect,cornerRadii:CornerRadii) -> CGPath { let minX = bounds.minX let minY = bounds.minY let maxX = bounds.maxX let maxY = bounds.maxY //获取四个圆心 let topLeftCenterX = minX + cornerRadii.topLeft let topLeftCenterY = minY + cornerRadii.topLeft let topRightCenterX = maxX - cornerRadii.topRight let topRightCenterY = minY + cornerRadii.topRight let bottomLeftCenterX = minX + cornerRadii.bottomLeft let bottomLeftCenterY = maxY - cornerRadii.bottomLeft let bottomRightCenterX = maxX - cornerRadii.bottomRight let bottomRightCenterY = maxY - cornerRadii.bottomRight //虽然顺时针参数是YES,在iOS中的UIView中,这里实际是逆时针 let path :CGMutablePath = CGMutablePath(); //顶 左 path.addArc(center: CGPoint(x: topLeftCenterX, y: topLeftCenterY), radius: cornerRadii.topLeft, startAngle: CGFloat.pi, endAngle: CGFloat.pi * 3 / 2, clockwise: false) //顶右 path.addArc(center: CGPoint(x: topRightCenterX, y: topRightCenterY), radius: cornerRadii.topRight, startAngle: CGFloat.pi * 3 / 2, endAngle: 0, clockwise: false) //底右 path.addArc(center: CGPoint(x: bottomRightCenterX, y: bottomRightCenterY), radius: cornerRadii.bottomRight, startAngle: 0, endAngle: CGFloat.pi / 2, clockwise: false) //底左 path.addArc(center: CGPoint(x: bottomLeftCenterX, y: bottomLeftCenterY), radius: cornerRadii.bottomLeft, startAngle: CGFloat.pi / 2, endAngle: CGFloat.pi, clockwise: false) path.closeSubpath(); return path; } } // MARK: - UIView的一些其他方法 public extension UIView { // MARK: - 键盘收起来 /// 键盘收起来 func keyboardEndEditing() { self.endEditing(true) } // MARK: 将 View 转换成图片 /// 将 View 转换成图片 /// - Returns: 图片 func toImage() -> UIImage { return UIGraphicsImageRenderer(size: self.frame.size).image { context in self.layer.render(in: context.cgContext) } } } // MARK: - Toast吐司🍞 extension UIView { // MARK: 普通消息 func toast(text: String) { var style = ToastStyle() style.messageFont = .textF(14) style.backgroundColor = UIColor.hexStringColor(hexString: "#000000", alpha: 0.85) style.cornerRadius = 8 style.verticalPadding = 14 style.horizontalPadding = 44 self.makeToast(text, duration: 1.5, position: .center, style: style) } }