Skip to content
  • Home
  • Code
  • iOS & Swift
  • Combine
  • RxSwift
  • SwiftUI
  • Flutter & Dart
  • Tutorials
  • Art
  • Blog
Fx Studio
  • Home
  • Code
  • iOS & Swift
  • Combine
  • RxSwift
  • SwiftUI
  • Flutter & Dart
  • Tutorials
  • Art
  • Blog
Written by chuotfx on July 12, 2021

Stack & Container – SwiftUI Notes #31

SwiftUI

Contents

  • Chuẩn bị
  • 1. HStack & VStack
    • 1.1. Định nghĩa
    • 1.2. Khởi tạo
    • 1.3. alignment
  • 2. ZStack
  • 3. Các containers khác
    • 3.1. Button
    • 3.2. Alert
  • Tạm kết

Chào bạn đến với Fx Studio. Chúng ta lại quay lại hành trình bất tận SwiftUI. Các bài viết trước thì bạn đã tìm hiểu về các UI Control cơ bản và kinh điển trong SwiftUI rồi. Bây giờ, chúng ta sẽ đi sang các UI Controls liên quan tới bố cục (layout). Đó là các Stack trong SwiftUI.

Nếu bạn chưa biết gì về Stack, thì mình đã có một bài viết các Stacks View. Bạn có thể đọc thêm tại đây. Và nếu mọi việc đã ổn rồi thì …

Bắt đầu thôi!

Chuẩn bị

Về mặt tool và version, các bạn tham khảo như sau:

    • SwiftUI 2.0
    • Xcode 12

Về mặt kiến thức, bạn cần biết trước các kiến thức cơ bản với SwiftUI & SwiftUI App. Tham khảo các bài viết sau, nếu bạn chưa đọc qua SwiftUI:

    • Làm quen với SwiftUI
    • Cơ bản về ứng dụng SwiftUI App

Về mặt demo, hầu như là demo đơn giản, vì tập trung vào từng View riêng lẻ. Do đó, bạn cũng không cần phải quá lo lắng và việc tạo mới project cũng không ảnh hưởng gì nhiều. Ngoài ra, bạn có thể checkout mã nguồn của các bài viết tại đây.

(Mặc định, mình xem như bạn đã biết về cách tạo project với SwiftUI & SwiftUI App rồi.)

1. HStack & VStack

1.1. Định nghĩa

Về định nghĩa các Stack, bạn hãy xem ở bài viết cơ bản này. Bây giờ, chúng ta sẽ chỉ nói về một số đặc điểm mới và kết hợp với Layout giữa chúng.

HStack & VStack tuy 2 đối tượng SwiftUI View khác nhau, nhưng về bản chất lại giống nhau. Khác nhau duy nhất ở chỗ hướng sắp xếp items trong chúng:

  • HStack sắp xếp các items theo chiều ngang
  • VStack sắp xếp các item theo chiều dọc

Với UIKit, chúng ta có người anh em UIStackView, nó cũng khá là tương tự với 2 Stack kia. Việc định hướng các items dựa theo thuộc tính axis.

1.2. Khởi tạo

Ta hãy sử dụng các Stack này, mà ít khi khám phá xem nó có những gì. Hầu như ta chỉ đặt các View vào giữa 2 dấu { } mà thôi. Bây giờ, ta xem hàm khởi tạo của chúng có gì.

// HStack
init(
  alignment: VerticalAlignment = .center,
  spacing: CGFloat? = nil,
  @ViewBuilder content: () -> Content
)

// VStack
init(
  alignment: HorizontalAlignment = .center,
  spacing: CGFloat? = nil,
  @ViewBuilder content: () -> Content
)

Trong đó:

  • content chính là cái thứ mà bạn hay đặt đám View vào giữa 2 dấu { }. Kiểu của nó là @ViewBuilder
  • alignment là căn chỉnh theo chiều ngang hay chiều dọc cho HStack hoặc VStack. Mặc định sẽ là .center cho cả 2
  • spacing khoảng cách giữa các phần tử. Mặc định là nil, Stack sẽ hiển thị khoảng cách dựa theo nền tảng. Muốn không có khoảng cách thì gán bằng 0

1.3. alignment

Cũng là khá phong phú cho cách hiển thị với thuộc tính alignment này. Với VStact, bạn có .center,  .leading,  .trailing. Đối với HStack, sẽ phong phú hơn nhiều thêm một tí. Ngoài .center, .top và .bottom thì có thêm:

  • firstTextBaseline : Căn chỉnh các chế độ xem dựa trên chế độ xem đường cơ sở văn bản trên cùng.
  • lastTextBaseline : Căn chỉnh các chế độ xem dựa trên chế độ xem đường cơ sở dưới cùng của văn bản.

Hi vọng bạn tận dùng được tối đa sức mạnh của chúng trong việc bố cục các văn bản mà có sự khác nhau giữa các font chữ và kích thước font chữ ….

Ta xem qua một chút ví dụ cho nó có màu mè trực quan xí.

var body: some View {
    HStack(alignment: .top) {
        Text("Welcome to Fx Studio").font(.caption)
        Text("Welcome to Fx Studio").font(.title)
        Button(action: {}, label: { Text("OK").font(.body) })
    }
}

Xem qua kết quả của nó tí nha.

Stack View

Để ý thật kĩ, bạn sẽ thấy điều kì diệu nhoé! Mặc dù ta để chế độ .top , tuy nhiên phần tử View ở giữa lại cách mép trên 1 đoạn. Và các phần tử nhìn lồi lõm rất khó chịu phải không nào. Bạn chỉ cần thay đổi từ .top thành .firstTextBaseline.

var body: some View {
    HStack(alignment: .firstTextBaseline) {
        Text("Welcome to Fx Studio").font(.caption)
        Text("Welcome to Fx Studio").font(.title)
        Button(action: {}, label: { Text("OK").font(.body) })
    }
}

Xem kết quả nhoé!

Stack View

Chúng nó đã ở cùng trên 1 dòng rồi. Mặc dù font chữ & size khác nhau. Đẹp rồi á!

2. ZStack

Với đối tượng ZStack này thì là đặc trưng riêng của SwiftUI. UIKit không có đối tượng tương tự như vậy. ZStack này có gì:

  • Các View con được xếp chồng lên nhau
  • View con đầu tiền sẽ ở dưới cùng
  • Các View vào sau sẽ ở trên các View vào trước
  • .layoutPriority sẽ không ảnh tới thứ tự ưu tiên của Layout

Về kích thước của ZStack sẽ được xác định dựa vào kích thước view con lớn nhất.

Về ứng dụng của Stack được dùng nhiều nhất cho việc xếp chồng các View lên với nhau. Bạn xem qua ví dụ sau nha.

ZStack (alignment: .bottom) {
     VStack(spacing: 0) {
         Rectangle()
             .frame(height: 90)
             .foregroundColor(
                 Color(red: 84.0/255.0, green: 61.0/255.0, blue: 1).opacity(1.0))
         Rectangle()
             .frame(height: 90)
             .foregroundColor(
                 Color(red: 84.0/255.0, green: 32.0/255.0, blue: 46.0/255.0).opacity(1.0))
     }
     
     Image("logo")
         .resizable()
         .frame(height: .infinity)
         .scaledToFit()
         .clipShape(Circle())
         .padding()
     
     VStack {
         Spacer()
         Text("Welcome to")
             .font(.body)
             .foregroundColor(.white)
         Text("Fx Studio")
             .font(.largeTitle)
             .foregroundColor(.white)
             .fontWeight(.bold)
             .shadow(radius: 7)
     }
     .padding()
 }
 .frame(height: 180)

Trong ví dụ trên, ý đồ sẽ là:

  • 2 View làm màu nền cho cả View lớn
  • 1 Image sẽ là logo và xếp chồng lên 2 View nền
  • 2 Text sẽ ở trên Image

Xem kết quả nhoé! Bạn hãy cố suy nghĩ cách hiển thị giữa các Stack ngay trong đầu mình và đối chiếu với kết quả xem có giống với ý đồ của mình hay không.

Stack View

Chúng ta thực hiện đè lên nhau giữa Image logo và các Text.

3. Các containers khác

Trong SwiftUI, ngoài các nhóm View cơ bản (là View mà không chứa các View nào nữa) thì chúng ta có các View được gọi là Container (là View mà chứa được nhiều View).

Ở phần trên, bạn đã khám khá các Container là Stacks View. Tuy nhiên, vẫn còn nhiều loại khác mà bạn cảm thấy bất ngờ.

(Mình chỉ ví dụ vài loại cơ bản mà thôi.)

3.1. Button

Đối tượng này khác là đơn giản. Tuy nhiên, chúng ta dùng hàm khởi tạo như đoạn code ví dụ sau:

Button(action: {}, label: {
     HStack {
         Image(systemName: "checkmark")
             .font(.largeTitle)
         Text("OK")
             .font(.largeTitle)
             .fontWeight(.bold)
     }
     .kute()
     .padding()
 })

Trong đó, label là một. ViewBuilder. Và bạn có thể thêm nhiều loại View vào đây. Nếu chúng nó là một. Stacks View thì lại có thể chứa thêm nhiều View con nữa. Đúng là khá thú vị phải không nào.

Xem kết quả nhoé!

3.2. Alert

Cũng tương tự như Button, với. Alert thì ta lại có nhiều tham số với kiểu dữ liệu là @ViewBuilder. Do đó, đối tượng View này cũng chứa nhiều hơn một View. Nhưng nó không thực sự là một Stack View.

Ví dụ code thì đơn giản như sau:

VStack {
    // ......
     }     
     .alert(isPresented: $isAlert: {
         Alert(title: Text("Fx Studio"),
               message: Text("Hello world!"),
               dismissButton: .default(Text("Got it!"))
         )
     })

Vẫn còn nhiều loại. Containers khác, tuy nhiên mình chỉ giới thiệu đại diện với 2 đối tượng là. Button &. Alert thôi. Các bạn từ từ khám phá sau nhoé.

Tạm kết

  • Bài viết chỉ nhắc lại các kiến thức về các Stack.
  • Giải thích thêm vào các tham số của mỗi loại.
  • Giới thiệu thêm vài đối tượng Containers khác hoặc được xem là containers

 

Okay! Tới đây, mình xin kết thúc bài viết về đối tượng Stack & Container trong SwiftUI. Và nếu có gì thắc mắc hay góp ý cho mình thì bạn có thể để lại bình luận hoặc gởi email theo trang Contact.

  • Bạn có thể checkout code tại đây.
  • Bài viết tiếp theo tại đây.

Cảm ơn bạn đã đọc bài viết này!

FacebookTweetPinYummlyLinkedInPrintEmailShares5

Related Posts:

  • feature_bg_swiftui_7
    Giới thiệu MapKit trên SwiftUI
Tags: SwiftUI, SwiftUI Notes
Written by chuotfx

Hãy ngồi xuống, uống miếng bánh và ăn miếng trà. Chúng ta cùng nhau đàm đạo về đời, về code nhóe!

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Donate – Buy me a coffee!

Fan page

Fx Studio

Tags

Actor Advanced Swift AI api AppDistribution autolayout basic ios tutorial blog ci/cd closure collectionview combine concurrency crashlytics dart dart basic dart tour Declarative delegate deploy design pattern fabric fastlane firebase flavor flutter GCD gradients iOS MVVM optional Prompt engineering protocol Python rxswift safearea Swift Swift 5.5 SwiftData SwiftUI SwiftUI Notes tableview testing TravisCI unittest

Recent Posts

  • Role-playing vs. Persona-based Prompting
  • [Swift 6.2] Raw Identifiers – Đặt tên hàm có dấu cách, tại sao không?
  • Vibe Coding là gì?
  • Cách Đọc Sách Lập Trình Nhanh và Hiệu Quả Bằng GEN AI
  • Nỗ Lực – Hành Trình Kiến Tạo Ý Nghĩa Cuộc Sống
  • Ai Sẽ Là Người Fix Bug Khi AI Thống Trị Lập Trình?
  • Thời Đại Của “Dev Tay To” Đã Qua Chưa?
  • Prompt Engineering – Con Đường Để Trở Thành Một Nghề Nghiệp
  • Vấn đề Ảo Giác (hallucination) khi tương tác với Gen AI và cách khắc phục nó qua Prompt
  • Điều Gì Xảy Ra Nếu… Những Người Dệt Mã Trở Thành Những Người Bảo Vệ Cuối Cùng Của Sự Sáng Tạo?

You may also like:

  • Giới thiệu MapKit trên SwiftUI
    feature_bg_swiftui_7

Archives

  • May 2025 (2)
  • April 2025 (1)
  • March 2025 (8)
  • January 2025 (7)
  • December 2024 (4)
  • September 2024 (1)
  • July 2024 (1)
  • June 2024 (1)
  • May 2024 (4)
  • April 2024 (2)
  • March 2024 (5)
  • January 2024 (4)
  • February 2023 (1)
  • January 2023 (2)
  • November 2022 (2)
  • October 2022 (1)
  • September 2022 (5)
  • August 2022 (6)
  • July 2022 (7)
  • June 2022 (8)
  • May 2022 (5)
  • April 2022 (1)
  • March 2022 (3)
  • February 2022 (5)
  • January 2022 (4)
  • December 2021 (6)
  • November 2021 (8)
  • October 2021 (8)
  • September 2021 (8)
  • August 2021 (8)
  • July 2021 (9)
  • June 2021 (8)
  • May 2021 (7)
  • April 2021 (11)
  • March 2021 (12)
  • February 2021 (3)
  • January 2021 (3)
  • December 2020 (3)
  • November 2020 (9)
  • October 2020 (7)
  • September 2020 (17)
  • August 2020 (1)
  • July 2020 (3)
  • June 2020 (1)
  • May 2020 (2)
  • April 2020 (3)
  • March 2020 (20)
  • February 2020 (5)
  • January 2020 (2)
  • December 2019 (12)
  • November 2019 (12)
  • October 2019 (19)
  • September 2019 (17)
  • August 2019 (10)

About me

Education, Mini Game, Digital Art & Life of coders
Contacts:
contacts@fxstudio.dev

Fx Studio

  • Home
  • About me
  • Contact us
  • Mail
  • Privacy Policy
  • Donate
  • Sitemap

Categories

  • Art (1)
  • Blog (44)
  • Code (11)
  • Combine (22)
  • Flutter & Dart (24)
  • iOS & Swift (102)
  • No Category (1)
  • RxSwift (37)
  • SwiftUI (80)
  • Tutorials (87)

Newsletter

Stay up to date with our latest news and posts.
Loading

    Copyright © 2025 Fx Studio - All rights reserved.