2025-07-13

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)

        }

    }

}

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容