this is what I am trying to do:
Is anyone know how can i do it in swift? I know there are some libraries that do something similar but I am trying to do it myself
this is what I am trying to do:
Is anyone know how can i do it in swift? I know there are some libraries that do something similar but I am trying to do it myself
You can achieve something like that with UICollectionView and custom UICollectionViewLayout
Some examples:
Sure. Set up constraints with offsets from your center point, and use trig to calculate the offsets. The code might look something like this:
let steps = 16 // The number of buttons you want
let radius = 75.0. // Your desired circle radius, in points
let angleStep = Double.pi * 2.0 / Double(steps)
for index in 0 ..< steps {
let angle = Double(index) * angleStep
let xOffset = CGFloat(radius * cos(angle))
let yOffset = CGFloat(radius * sin(angle))
// add button to superview with center anchored to center of superview
// offset by xOffset and yOffset
}
I mostly create my views and controls using storyboards, so this was a good excuse to practice creating them in code. I made a demo project on github that creates a circle of buttons. You can download it here:
https://github.com/DuncanMC/ButtonsInCircle.git
All the logic is in the View controller's source file:
//
// ViewController.swift
// ButtonsInCircle
//
// Created by Duncan Champney on 2/28/21.
//
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var titleLabel: UILabel!
@IBOutlet weak var buttonContainerView: UIView!
let buttonCount = 12 //The number of buttons to create
var angleStep: Double = 0 //The change in angle between buttons
var radius: CGFloat = 75.0 // The radius to use (will be updated at runtime based on the size of the container view.)
//A type to hold a layout anchor for a button, it's index, and whether it's a horizontal or veritical anchor
typealias ConstraintTuple = (index: Int, anchor: NSLayoutConstraint, axis: NSLayoutConstraint.Axis)
//An array of the layout anchors for our buttons.
var constraints = [ConstraintTuple]()
//Our layout has changed. Update the array of layout anchors
func updateButtonConstraints() {
for (index, constraint, axis) in self.constraints {
let angle = Double(index) * self.angleStep
let xOffset = self.radius * CGFloat(cos(angle))
let yOffset = self.radius * CGFloat(sin(angle))
if axis == .horizontal {
constraint.constant = xOffset
} else {
constraint.constant = yOffset
}
}
}
override func viewDidLayoutSubviews() {
//Pick a radius that's a little less than 1/2 the shortest side of our bounding rectangle
radius = min(buttonContainerView.bounds.width, buttonContainerView.bounds.height) / 2 - 30
print("Radius = \(radius)")
updateButtonConstraints()
}
func createButtons() {
for index in 0 ..< buttonCount {
//Create a button
let button = UIButton(primaryAction:
//Define the button title, and the action to trigger when it's tapped.
UIAction(title: "Button \(index+1)") { action in
print("Button \(index + 1) tapped")
}
)
button.translatesAutoresizingMaskIntoConstraints = false //Remember to do this for UIViews you create in code
button.layer.borderWidth = 1.0 // Draw a rounded rect around the button so you can see it
button.layer.cornerRadius = 5
button.setTitle("\(index+1)", for: .normal)
button.setTitleColor(.blue, for: .normal)
//Add it to the container view
buttonContainerView.addSubview(button)
button.sizeToFit()
//Create center x & y layout anchors (with no offset to start)
let buttonXAnchor = button.centerXAnchor.constraint(equalTo: buttonContainerView.centerXAnchor, constant: 0)
buttonXAnchor.isActive = true
//Add a tuple for this layout anchor to our array
constraints.append(ConstraintTuple(index: index, anchor: buttonXAnchor, axis: .horizontal))
let buttonYAnchor = button.centerYAnchor.constraint(equalTo: buttonContainerView.centerYAnchor, constant: 0)
buttonYAnchor.isActive = true
//Add a tuple for this layout anchor to our array
constraints.append(ConstraintTuple(index: index, anchor: buttonYAnchor, axis: .vertical))
}
}
override func viewDidLoad() {
super.viewDidLoad()
angleStep = Double.pi * 2.0 / Double(buttonCount)
createButtons()
}
}
It looks like this when you run it:

(On iOS, the starting angle (0°) is "East" in terms of a compass. If you want your first button to start at the top you'd have to add an offset to your starting angle.)
You can position any view anywhere using either offset(x: y) or position(x:y).
Offset this view by the specified horizontal and vertical distances. - https://developer.apple.com
Positions the center of this view at the specified coordinates in its parent’s coordinate space.https://developer.apple.com
For instance:
ZStack {
Text("A")
.background(Color.red)
.position(x: 10, y: 20)
Text("b")
.background(Color.red)
.position(x: 50, y: 30)
Text("c")
.background(Color.red)
.position(x: 100, y: 40)
Text("d")
.background(Color.red)
.position(x: 150, y: 200)
}
Find the exact x and y position yourself
Fore more info, read this articel https://www.hackingwithswift.com/books/ios-swiftui/absolute-positioning-for-swiftui-views