首页 > 解决方案 > 我想创建一个半圆形菜单,有 N 个菜单项

问题描述

我想创建一个这样的菜单,

菜单图片(共 4 项).

但是没有为菜单项(UIButton)获得完美的中心点,我正在使用Stride(from:)ingetCirclePoints()为菜单项获取 CGPoint,从起始角度和结束角度具有相等的间距。

numberOfViews变量包含我想要放置的菜单项的数量。

如果numberOfViews = 5那时,输出将是

5 道菜的菜单.

任何人都有更好的想法来创建这样的动态菜单,或者在这段代码中帮助我。

谢谢你。

class ViewController: UIViewController {

    @IBOutlet weak var btnMenu: UIButton!

    var numberOfViews: Int = 4
    var arrPoints: [CGPoint] = []
    var arrMenuItems = [UIButton]()

    var menuFrame: CGRect!
    var itemFrame: [CGRect] = []
    var isMenuOpen = false

    override func viewDidLoad() {
        super.viewDidLoad()
        prepareUI()
    }

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
    }
}

extension ViewController {

    @IBAction func btnMenuTapped(_ sender: UIButton) {
        menu(open: isMenuOpen)
    }
}

extension ViewController {

    func prepareUI() {
        createMenuItems()
        storeFrame()
        btnMenu.makeRounded(0, isFullyRounded: true)
        menu(open: false, withDuration: 0.0001)
    }

    func createMenuItems() {
        arrPoints = getCirclePoints(centerPoint: btnMenu.center, radius: (self.view.bounds.width/CGFloat(numberOfViews) + 25), n: numberOfViews)
        for i in 0..<numberOfViews {
            drawMenuItem(for: i)
        }
    }

    func drawMenuItem(for index: Int) {
        var menuItem: UIButton
        let rect = CGRect(x: arrPoints[index].x, y: arrPoints[index].y, width: 50, height: 50)
        menuItem = UIButton(frame: rect)
        menuItem.makeRounded(0, isFullyRounded: true)
        menuItem.backgroundColor = UIColor.randomColor
        arrMenuItems.append(menuItem)
        view.addSubview(menuItem)
    }

    func getCirclePoints(centerPoint point: CGPoint, radius: CGFloat, n: Int)->[CGPoint] {
        let result: [CGPoint] = stride(from: -168, to: 12, by: Double(180 / n)).map {
            let bearing = CGFloat($0) * .pi / 180
            let x = point.x + radius * cos(bearing)
            let y = point.y + radius * sin(bearing)
            return CGPoint(x: x, y: y)
        }
        return result
    }

    func storeFrame() {
        menuFrame = btnMenu.frame
    }

    func menu(open isOpen: Bool, withDuration duration: Double = 0.5) {
        if isOpen {
            self.view.bringSubviewToFront(self.btnMenu)
            UIView.animate(withDuration: duration, animations: {
                for element in self.arrMenuItems {
                    element.frame = self.menuFrame
                }
            }) { (completed) in
                self.isMenuOpen = !self.isMenuOpen
            }
        }else {
            UIView.animate(withDuration: duration, animations: {
                for (index, element) in self.arrMenuItems.enumerated() {
                    element.frame = CGRect(x: self.arrPoints[index].x, y: self.arrPoints[index].y, width: element.frame.width, height: element.frame.height)
                }
                self.view.layoutIfNeeded()
            }) { (completed) in
                self.isMenuOpen = !self.isMenuOpen
            }
        }
    }
}

extension UIButton {

    func makeRounded(_ cornerRadius: CGFloat, isFullyRounded: Bool) {
        if isFullyRounded {
            self.layer.cornerRadius = self.frame.width / 2
        }else {
            self.layer.cornerRadius = cornerRadius
        }
    }
}

// MARK:- Color extension
extension UIColor {

    // To get random color
    static var randomColor: UIColor {
        return UIColor(red: .random(in: 0...1), green: .random(in: 0...1), blue: .random(in: 0...1), alpha: 1.0)
    }
}

标签: iosswiftanimationmenu

解决方案


您可以使用fan-menu库进行半圆形菜单


推荐阅读