import UIKit
class PopView: UIView {
@IBOutlet weak var textContainerView: UIView! // 包裹 UILabel 的外层视图
@IBOutlet weak var textLabel: UILabel! // 显示文本的 UILabel
@IBOutlet weak var scrollView: UIScrollView! // 用于处理滚动的 ScrollView
private var arrowLayer: CAShapeLayer!
private var arrowDirection: ArrowDirection = .down
enum ArrowDirection {
case up, down, left, right
}
override func awakeFromNib() {
super.awakeFromNib()
setupArrowLayer()
}
// 配置 PopView 并自动调整内容
func configure(with text: String, arrowDirection: ArrowDirection, at point: CGPoint) {
textLabel.text = text
self.arrowDirection = arrowDirection
setupArrow()
// 不需要手动设置 PopView 的 frame,Auto Layout 会自动处理
positionView(at: point)
}
private func setupArrowLayer() {
if arrowLayer == nil {
arrowLayer = CAShapeLayer()
layer.addSublayer(arrowLayer)
}
}
private func setupArrow() {
let arrowPath = UIBezierPath()
switch arrowDirection {
case .up:
arrowPath.move(to: CGPoint(x: bounds.width / 2, y: 0))
arrowPath.addLine(to: CGPoint(x: bounds.width / 4, y: 20))
arrowPath.addLine(to: CGPoint(x: 3 * bounds.width / 4, y: 20))
arrowPath.close()
case .down:
arrowPath.move(to: CGPoint(x: bounds.width / 2, y: bounds.height))
arrowPath.addLine(to: CGPoint(x: bounds.width / 4, y: bounds.height - 20))
arrowPath.addLine(to: CGPoint(x: 3 * bounds.width / 4, y: bounds.height - 20))
arrowPath.close()
case .left:
arrowPath.move(to: CGPoint(x: 0, y: bounds.height / 2))
arrowPath.addLine(to: CGPoint(x: 20, y: bounds.height / 4))
arrowPath.addLine(to: CGPoint(x: 20, y: 3 * bounds.height / 4))
arrowPath.close()
case .right:
arrowPath.move(to: CGPoint(x: bounds.width, y: bounds.height / 2))
arrowPath.addLine(to: CGPoint(x: bounds.width - 20, y: bounds.height / 4))
arrowPath.addLine(to: CGPoint(x: bounds.width - 20, y: 3 * bounds.height / 4))
arrowPath.close()
}
arrowLayer.path = arrowPath.cgPath
arrowLayer.fillColor = UIColor.black.cgColor
}
// 计算 PopView 的位置,箭头指向给定的点
private func positionView(at point: CGPoint) {
switch arrowDirection {
case .up:
self.frame.origin = CGPoint(x: point.x - self.frame.width / 2, y: point.y)
case .down:
self.frame.origin = CGPoint(x: point.x - self.frame.width / 2, y: point.y - self.frame.height)
case .left:
self.frame.origin = CGPoint(x: point.x, y: point.y - self.frame.height / 2)
case .right:
self.frame.origin = CGPoint(x: point.x - self.frame.width, y: point.y - self.frame.height / 2)
}
}
}