How to plot circular buttons around a central poin

2019-09-25 06:33发布

This question already has an answer here:

I am attempting to plot circular buttons in a ring like this.

enter image description here

I have 6 UI buttons which all have a corner-radius of 360 degrees, what I am attempting to do in Swift is plot them equally around a central button/point just like the image above. Each circle is equally spaced from its neighbour. What is the best way of achieving this functionality? Should I create a bezier curve and then use math to plot the buttons around said curve or is there another way which you would suggest?

A side note is that I am not looking for a radial menu of any kind there is no animation required. I am just trying to plot my existing UI Buttons in the format above.

Thanks!

2条回答
贼婆χ
2楼-- · 2019-09-25 06:57

You don't need a bezierpath for that, just a bit of calculation.

I am not a math genius or something so I took an already answered question and changed it to my needs.

func place(buttons: [UIView], around center: CGPoint, radius: CGFloat) {
    var currentAngle: CGFloat = 0
    let buttonAngle: CGFloat = (CGFloat(360 / buttons.count)) * .pi / 180

    for button in buttons {
        let buttonCenter = CGPoint(x: center.x + cos(currentAngle) * radius, y: center.y + sin(currentAngle) * radius)

        // (1)
        //button.transform = CGAffineTransform(rotationAngle: currentAngle)

        // (2)
        //view.addSubview(button)

        button.center = buttonCenter
        currentAngle += buttonAngle
    }
}

Use an array of UIView so you are flexible. If you want to add the buttons from code, just uncomment (1). If you want the buttons to rotate according to their rotation around the center, uncomment (2).

Btw it is not necessary to add 360 degree cornerradius to the buttons for a round shape. Please have a read on the documentation here.

Happy coding!

查看更多
做个烂人
3楼-- · 2019-09-25 07:16

I would suggest using math (trigonometry) to compute the horizontal and vertical offsets from the center button and then use layout anchors to position the buttons.

Here is a self contained example:

class ViewController: UIViewController {

    func createButton(size: CGFloat) -> UIButton {
        let button = UIButton(type: .custom)
        button.backgroundColor = .red
        button.translatesAutoresizingMaskIntoConstraints = false
        button.widthAnchor.constraint(equalToConstant: size).isActive = true
        button.heightAnchor.constraint(equalToConstant: size).isActive = true
        button.layer.cornerRadius = size / 2

        return button
    }

    func setUpButtons(count: Int, around center: UIView, radius: CGFloat) {
        // compute angular separation of each button
        let degrees = 360 / CGFloat(count)

        for i in 0 ..< count {
            let button = createButton(size: 50)
            self.view.addSubview(button)

            // use trig to compute offsets from center button
            let hOffset = radius * cos(CGFloat(i) * degrees * .pi / 180)
            let vOffset = radius * sin(CGFloat(i) * degrees * .pi / 180)

            // set new button's center relative to the center button's
            // center using centerX and centerY anchors and offsets
            button.centerXAnchor.constraint(equalTo: center.centerXAnchor, constant: hOffset).isActive = true
            button.centerYAnchor.constraint(equalTo: center.centerYAnchor, constant: vOffset).isActive = true
        }
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        let centerButton = createButton(size: 50)
        self.view.addSubview(centerButton)

        // use anchors to place center button in the center of the screen
        centerButton.centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true
        centerButton.centerYAnchor.constraint(equalTo: self.view.centerYAnchor).isActive = true

        setUpButtons(count: 6, around: centerButton, radius: 100)
    }

}

Notes:

  • If you don't need the center button, just set up the buttons around self.view:

    setupButtons(count: 6, around: self.view, radius: 100)
    

    or around an arbitrary point:

    let point = CGPoint(x: 180, y: 300)
    let centerView = UIView(frame: CGRect(origin: point, size: CGSize.zero))
    self.view.addSubview(centerView)
    setUpButtons(count: 6, around: centerView, radius: 140)
    
  • Using a UIView as the center instead of a point is more flexible because you can dynamically move that UIView and the buttons will follow.

Here it is running in the simulator:

Demo running in the simulator

查看更多
登录 后发表回答