How to plot circular buttons around a central point in a ring? [duplicate]

人盡茶涼 提交于 2019-12-13 11:14:57

问题


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

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!


回答1:


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:




回答2:


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!



来源:https://stackoverflow.com/questions/54234082/how-to-plot-circular-buttons-around-a-central-point-in-a-ring

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!