Programmatic Auto Layout

Oğuzhan Akın
3 min readJan 4, 2023

--

Programmatic UI denilince en korkulan işlerden biri constraintleri ayarlamak, Auto Layout konusu akla geliyor, bu uğraş gerektiren kısmı daha rahat çözebilmek için en çok kullanılan Swift Package Manager’lardan biri olan Snapkit tercih edilirken biz burada farklı bir yol izleyerek UI View sınıfına extension yazacağız.

Extension Yazmak

Yeni bir ekran oluşturmak istediğimizde bu ekranı UIViewController sınıfına bağlarız ve gerekli işlemlerimizi bu sınıf içerisinde yaparız. UIViewController aynı zamanda UIView’in bir alt sınıfıdır ve bu nedenle UIView’e yazacağımız extension içerisindeki methodları controller içerisinde de kullanmak imkanımız olacak.

Extension yazmadan ya da herhangi bir paket kütüphane kullanmadan bu constraintler’i UIKit’in bize doğrudan verdiği fonksiyonlar ile kullanabilirdik ancak her bir constraint’i ayrı bir fonksiyon çağırıp alt alta belirtmemiz gerekecek ve her seferinde daha fazla kod yazmamıza neden olacaktı. Aşağıda paylaştığım extension’ı ayrı bir swift dosyası oluşturup projemize ekleyebiliriz. UIView sınıfında türeceğimiz her sınıfta ve her nesnede bu fonksiyonları çağırıp hızlıca constraintlerimizi verebiliyor olacağız.

extension UIView {
func anchor(top: NSLayoutYAxisAnchor? = nil,
left: NSLayoutXAxisAnchor? = nil,
bottom: NSLayoutYAxisAnchor? = nil,
right: NSLayoutXAxisAnchor? = nil,
paddingTop: CGFloat = 0,
paddingLeft: CGFloat = 0,
paddingBottom: CGFloat = 0,
paddingRight: CGFloat = 0,
width: CGFloat? = nil,
height: CGFloat? = nil) {

translatesAutoresizingMaskIntoConstraints = false

if let top = top {
topAnchor.constraint(equalTo: top, constant: paddingTop).isActive = true
}

if let left = left {
leftAnchor.constraint(equalTo: left, constant: paddingLeft).isActive = true
}

if let bottom = bottom {
bottomAnchor.constraint(equalTo: bottom, constant: -paddingBottom).isActive = true
}

if let right = right {
rightAnchor.constraint(equalTo: right, constant: -paddingRight).isActive = true
}

if let width = width {
widthAnchor.constraint(equalToConstant: width).isActive = true
}

if let height = height {
heightAnchor.constraint(equalToConstant: height).isActive = true
}
}

func center(inView view: UIView, yConstant: CGFloat? = 0) {
translatesAutoresizingMaskIntoConstraints = false
centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
centerYAnchor.constraint(equalTo: view.centerYAnchor, constant: yConstant!).isActive = true
}

func centerX(inView view: UIView, topAnchor: NSLayoutYAxisAnchor? = nil, paddingTop: CGFloat? = 0) {
translatesAutoresizingMaskIntoConstraints = false
centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true

if let topAnchor = topAnchor {
self.topAnchor.constraint(equalTo: topAnchor, constant: paddingTop!).isActive = true
}
}

func centerY(inView view: UIView, leftAnchor: NSLayoutXAxisAnchor? = nil, paddingLeft: CGFloat? = nil, constant: CGFloat? = 0) {
translatesAutoresizingMaskIntoConstraints = false

centerYAnchor.constraint(equalTo: view.centerYAnchor, constant: constant!).isActive = true

if let leftAnchor = leftAnchor, let padding = paddingLeft {
self.leftAnchor.constraint(equalTo: leftAnchor, constant: padding).isActive = true
}
}

func setDimensions(width: CGFloat, height: CGFloat) {
translatesAutoresizingMaskIntoConstraints = false
widthAnchor.constraint(equalToConstant: width).isActive = true
heightAnchor.constraint(equalToConstant: height).isActive = true
}

func addConstraintsToFillView(_ view: UIView) {
translatesAutoresizingMaskIntoConstraints = false
anchor(top: view.topAnchor, left: view.leftAnchor,
bottom: view.bottomAnchor, right: view.rightAnchor)
}
}

Aşağıda bir kod kullanımı bırakıyorum sadece bu aşamada örnek olması amacıyla, öncesinde oluşturulan bir stack yapısı addSubview ile view’e eklenir, UIView sınıfında oluşturulan stack yapısında kendi yazdığımız anchor fonksiyonunu çağırarak X ve Y ekseninde nereden hiza alacağını ve ne kadar boşluk bırakmak istediğimiz belirterek Constraintleri vermiş oluruz.

view.addSubview(stack)
stack.anchor(top: titleLabel.bottomAnchor, left: view.leftAnchor,
right: view.rightAnchor, paddingTop: 40,
paddingLeft: 16, paddingRight: 16)

Bir sonraki yazımda Programmatic UI elemanları oluşturma konusuna değineceğim ve bunu yaparken closure’lardan faydalanacağız.

https://medium.com/@ogushanakin/programmatic-components-3051b79a994a

--

--