Published on

SwiftUI-da Alignment Guide'lardan qanday foydalanish kerak

Authors

Alignment Guide — SwiftUI'da biror elementning hizalanishini (alignment) aniq sozlash imkonini beruvchi vosita. Bu xususiyat SwiftUI'ning dastlabki versiyasidan beri mavjud, ammo kamdan-kam ishlatiladi. Ko'pchilik holatlarda padding, offset yoki Spacer yetarli — alignment guide esa faqat ular yetmagan paytda kerak bo'ladi.


padding / offset va alignment guide farqi

VStack(alignment: .leading) {
    Text("Hello, World!")
        .background(Color.blue)

    Text("This is some other text")
        .background(Color.red)
}
.background(Color.orange)

Bu oddiy VStack. Endi birinchi matnni biroz ichkariga surishni xohlaymiz.

padding bilan:

Text("Hello, World!")
    .padding(.leading, 10)
    .background(Color.blue)

Matn siljiydi, ammo VStackning orange foni o'zgarmaydi — fon hamon chap chekkadan boshlanadi.

offset bilan:

Text("Hello, World!")
    .offset(x: 20)
    .background(Color.blue)

Xuddi shu natija — matn siljiydi, VStack foni o'zgarmaydi.

alignment guide bilan:

Text("Hello, World!")
    .alignmentGuide(.leading) { dimensions in
        return -20
    }
    .background(Color.blue)

Bu holda esa VStack alignment'i o'zgaradi — orange fon ham kengayadi, chunki biz VStackning o'zini emas, shu elementning VStack ichidagi hizalanish nuqtasini o'zgartirmoqdamiz.


dimensions.width — geometryReader'siz kenglik olish

Alignment guide'ning kuchli tomoni — dimensions parametri elementning o'lchamlarini bevosita beradi:

Text("Hello, World!")
    .alignmentGuide(.leading) { dimensions in
        dimensions.width
    }
    .background(Color.blue)

Bu matnni o'z kengligi qadar o'ngga siljitadi — GeometryReader ishlatmasdan. Yarmiga siljitish uchun:

Text("Hello, World!")
    .alignmentGuide(.leading) { dimensions in
        dimensions.width * 0.5
    }

Bu, ayniqsa matn o'lchamlari dinamik bo'lganda (kichik ekran, katta shrift) foydalanish ancha qulay.


Amaliy misol: qatorlarda ikonka/matn tekislash

Ko'p uchraydigan muammo — bir qatorda ikonka bor, boshqasida yo'q, ammo matnlar tekis turishi kerak:

struct AlignmentChildView: View {
    var body: some View {
        VStack(alignment: .leading, spacing: 20) {
            row(title: "Row 1", showIcon: false)
            row(title: "Row 2", showIcon: true)
            row(title: "Row 3", showIcon: false)
        }
        .padding(16)
        .background(Color.white)
        .cornerRadius(10)
        .shadow(radius: 10)
        .padding(40)
    }

    private func row(title: String, showIcon: Bool) -> some View {
        HStack(spacing: 10) {
            if showIcon {
                Image(systemName: "info.circle")
                    .frame(width: 30, height: 30)
            }
            Text(title)
            Spacer()
        }
    }
}

Muammo: 2-qatorda ikonka bor, 1 va 3-qatorda yo'q — shuning uchun ularning matnlari chap chekkadan tursa, 2-qatorning matni ikonka kengligidan boshlanadi. Tekislash buziladi.


Yechim 1: ikonkani har doim chizib, opacity bilan yashirish

Image(systemName: "info.circle")
    .frame(width: 30, height: 30)
    .opacity(showIcon ? 1 : 0)

Bu eng sodda yechim — ikonka hamma qatorda mavjud (joy egallaydi), ammo ko'rinmaydi. To'liq to'g'ri, ko'pchilik ishlatadi.


Yechim 2: alignment guide bilan (elementni chizmasdan)

private func row(title: String, showIcon: Bool) -> some View {
    HStack(spacing: 10) {
        if showIcon {
            Image(systemName: "info.circle")
                .frame(width: 30, height: 30)
        }
        Text(title)
        Spacer()
    }
    .alignmentGuide(.leading) { _ in
        showIcon ? -40 : 0
        // ikonka kengligi (30) + spacing (10) = 40
    }
}

Ikonkasi yo'q qatorlar chap chekkadan 40 piksel ichkariga siljiydi — shuning uchun matnlar 2-qatordagi matnga tekis turadi. Ikonka ekranga chizilmaydi, joy ham egallaydi.


To'liq kod

struct AlignmentGuideBootcamp: View {
    var body: some View {
        VStack(alignment: .leading) {
            Text("Hello, World!")
                .background(Color.blue)
                .alignmentGuide(.leading) { dimensions in
                    dimensions.width * 0.5
                }

            Text("This is some other text")
                .background(Color.red)
        }
        .background(Color.orange)
    }
}

struct AlignmentChildView: View {
    var body: some View {
        VStack(alignment: .leading, spacing: 20) {
            row(title: "Row 1", showIcon: false)
            row(title: "Row 2", showIcon: true)
            row(title: "Row 3", showIcon: false)
        }
        .padding(16)
        .background(Color.white)
        .cornerRadius(10)
        .shadow(radius: 10)
        .padding(40)
    }

    private func row(title: String, showIcon: Bool) -> some View {
        HStack(spacing: 10) {
            if showIcon {
                Image(systemName: "info.circle")
                    .frame(width: 30, height: 30)
            }
            Text(title)
            Spacer()
        }
        .alignmentGuide(.leading) { _ in
            showIcon ? -40 : 0
        }
    }
}

Xulosa

Alignment guide qachon kerak:

  • padding yoki offset ishlatib bo'lmaydi (fon kengayishi kerak)
  • Elementning o'z kengligiga bog'liq siljish kerak (dimensions.width)
  • GeometryReader ishlatsiz o'lcham olish kerak
  • Bir nechta qatordagi elementlar tekisligini ikonkasiz ham saqlash kerak

Qachon kerak emas (aksariyat hollarda):

  • Oddiy padding(.leading, N) yetarli
  • Spacer() yoki frame(maxWidth: .infinity) yetarli
  • Shunchaki elementni biroz siljitish kerak

Ko'plab ilovalar alignment guide'siz qurilgan — lekin kerak bo'lganda asboblar qutingizda bo'lishi shart.

Buy mea coffee