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 March 17, 2021

Basic Layout – SwiftUI Notes #11

SwiftUI

Contents

  • Chuẩn bị
  • 1. VStack
  • 2. HStack
  • 3. ZStack
  • 4. ScrollView
  • 5. Layout hỗn hợp
  • 6. Spacer
  • Tạm kết

Chào bạn đến với Fx Studio. Chúng ta đã đi qua nhiều bài viết về SwiftUI và series SwiftUI Notes. Bên cạnh đó, các kiến thức mới liên tục được cập nhật. Và mình hi vọng nó sẽ tạo được hứng thú cho bạn. Tiếp tục series, bài viết này sẽ trình bày chủ đề về bố cục giao diện của ứng dụng SwiftUI. Đó là Basic Layout trong SwiftUI.

Trước khi bắt đầu, mình tóm tắt cho bạn lại một số phần trước trong SwiftUI như sau:

    • Bắt đầu làm quen với SwiftUI.
    • Tìm hiểu về Declarative App với SwiftUI.
    • Sử dụng được các Declaring View
    • Cuối cùng là tự tạo các Custom View của riêng bạn bằng SwiftUI.

Và nếu như mọi việc đã ổn rồi, thì …

Bắt đầu thôi!

Chuẩn bị

Về môi trường cho demo, bạn có thể tham khảo như sau:

    • Xcode 12
    • Swift 5.3
    • SwiftUI 2.0

Vẫn là những yêu cầu cơ bản cho version các tools mà ta cần sử dụng. Bạn có thể checkout code tại đây:

    • Toàn bộ repo: https://github.com/fx-studio/swiftui-notes

Về demo của bài viết thì không quá cầu kì. Để bắt đầu, bạn hãy tạo một project mới bằng SwiftUI. Sau đó, bạn tạo thêm một Reusable View, để tái sử dụng nhiều lần cho demo của chúng ta. Mình sẽ đặt tên là ItemView và code ví dụ như sau:

struct ItemView: View {
    
    var width: CGFloat = 200
    var height: CGFloat = 100
    var name = ""
    var backgroundColor: Color = .blue
    
    var body: some View {
        Text(name)
            .foregroundColor(Color.white)
            .frame(width: width, height: height, alignment: .center)
            .background(backgroundColor)
            .padding(.all, 1.0)
    }
}

View này sẽ hiển thị một hình chữ nhật với màu nền mặc định là màu xanh. Ngoài ra, bạn có thể tuỳ chỉnh giá trị khởi tạo ban đầu của nó, bằng cách thêm các tham số vào hàm khởi tạo.

ItemView(width: 100, height: 100, name: "Image", backgroundColor: .gray)

 

Cuối cùng, thay vì nói lý thuyết nhiều. Mình hi vọng qua các demo tiếp theo, bạn có thể hiểu được các cách bố cục cơ bản mà SwiftUI cung cấp.

Nhân tiện là Autolayout hay xét frame của UIKit thì không còn nữa. Bạn hãy bắt đầu thay đổi suy nghĩ của mình với SwiftUI.

Nhưng ta có … Stacks trong SwiftUI. Và nó lại tương tự UIStackView trong UIKit. Về Stacks trong SwiftUI phân ra 3 loại:

  • Ngang (HStack)
  • Dọc (VStack)
  • Depth-based (ZStack)

Okay! Ta bắt đầu tìm hiểu từng loại thôi.

1. VStack

Bạn hãy tạo một file SwiftUI View mới và sử sử dụng Layout đầu tiên. Chính là VStack & code ví dụ như sau:

struct DemoVStack: View {
    var body: some View {
        VStack {
            ItemView(name: "1")
            ItemView(name: "2")
            ItemView(name: "3")
            ItemView(name: "4")
        }
    }
}

Bạn hãy chờ một tí và thấy màn hình Preview sẽ xuất hiện giao diện như sau:

VStack Layout - SwiftUI

VStack là gì?

  • Các View con trong nó sẽ được bố trí theo hàng ngang
  • Theo thứ tự từ trên xuống dưới
  • Mặc định thì tất cả sẽ canh chính giữa
  • Bạn có thể tuỳ biến thêm nhiều modifiers cho VStack

Tạm thời chúng ta xong về VStack. Tiến sang đối tượng tiếp theo nào!

2. HStack

Ta cũng sẽ demo Stack mới tương tự với VStack ở trên. Lần này, bạn sẽ dùng HStack. Ta xem đoạn code ví dụ sau:

struct DemoHStack: View {
    var body: some View {
        HStack(alignment: .center, spacing: 40) {
            ItemView(width: 50, height: 50, name: "1")
            ItemView(width: 50, height: 50, name: "2")
            ItemView(width: 50, height: 50, name: "3")
            ItemView(width: 50, height: 50, name: "4")
        }
    }
}

Bạn hãy xem kết quả hiển thị như thế nào?

Với HStack thì tương tự như VStack, nhưng sẽ bố cục theo hàng dọc và từ thứ tự từ trái sang phải.

Tiếp theo, ta tuỳ chỉnh một tí cho HStack như sau:

    • alignment để canh lề cho các View con
    • spacing tạo khoảng cách giữa các View con
HStack(alignment: .center, spacing: 40) {
    ItemView(width: 50, height: 50, name: "1")
    ItemView(width: 50, height: 50, name: "2")
    ItemView(width: 50, height: 50, name: "3")
    ItemView(width: 50, height: 50, name: "4")
}

Xem tiếp kết quả nhoé!

Khoảng cách giữa các phần tử đã giãn ra nhiều rồi. Giờ ta thử kết hợp giữa

VStack + HStack

Ví dụ code như sau:

VStack {
    HStack {
        ItemView(width: 50, height: 50, name: "1")
        ItemView(width: 50, height: 50, name: "2")
        ItemView(width: 50, height: 50, name: "3")
        ItemView(width: 50, height: 50, name: "4")
    }
    HStack {
        ItemView(width: 50, height: 50, name: "5")
        ItemView(width: 50, height: 50, name: "6")
        ItemView(width: 50, height: 50, name: "7")
        ItemView(width: 50, height: 50, name: "8")
    }
    HStack {
        ItemView(width: 50, height: 50, name: "9")
        ItemView(width: 50, height: 50, name: "10")
        ItemView(width: 50, height: 50, name: "11")
        ItemView(width: 50, height: 50, name: "12")
    }
    HStack {
        ItemView(width: 50, height: 50, name: "13")
        ItemView(width: 50, height: 50, name: "14")
        ItemView(width: 50, height: 50, name: "15")
        ItemView(width: 50, height: 50, name: "16")
    }
}

Với cách này, bạn có một CollectionView như ở UIKit. Tuy khá là thô sơ nhưng cũng đầy đủ chức năng của một UICollectionView. Thêm một vào for là xin sò thôi!

Grid Layout - SwiftUI

Okay, sang tiếp một loại Stack nữa nha!

3. ZStack

Đây là đối tượng Stack cuối, bạn xem tiếp ví dụ sau:

struct DemoZStack: View {
    var body: some View {
        ZStack(alignment: .bottomLeading) {
            ItemView(width: 300, height: 300, name: "1", backgroundColor: Color(.blue))
            ItemView(width: 200, height: 200, name: "2", backgroundColor: Color(.green))
            ItemView(width: 100, height: 100, name: "3", backgroundColor: Color(.red))
            ItemView(width: 50, height: 50, name: "4", backgroundColor: Color(.darkGray))
        }
    }
}

Kết quả hiển thị như sau:

Với ZStack:

  • Các view con sẽ được xếp chồng lên nhau
  • Thứ tự cuối cùng sẽ ở trên cùng

Nó sẽ phát huy hiệu quả khi bạn muốn view này đè view kia. Okay! Chúng ta chuyển sang loại Layout khác nữa.

4. ScrollView

Để hiển thị cho giao diện lớn hơn so với kích thước của màn hình hiển thị. Bạn phải dùng tới ScrollView. Bản chất thì nó giống như UIScrollView trong UIKit. Code sử dụng cho một ScrollView đơn giản như sau:

ScrollView {
   // ...
}
.frame(maxWidth: .infinity, maxHeight: .infinity)

Trong đó:

  • Bạn cần xác định kích thước của scroll thông qua modified .frame
  • Để full màn hình mà không cần quan tâm tới các kích thước của thiết bị khác nhau. Thì ta sử dụng tham số .infinity

5. Layout hỗn hợp

Bây giờ, ta sẽ sử dụng hỗn hợp các bố cùng vào ScrollView để xem kết quả như thế nào. Ví dụ đoạn code sau:

ScrollView {
            ZStack(alignment: .topLeading) {
                ItemView(width: 400, height: 200, name: "Banner")
                ItemView(width: 100, height: 100, name: "Image", backgroundColor: .gray)
            }
            HStack {
                ItemView(width: 100, height: 50, name: "Like")
                ItemView(width: 100, height: 50, name: "Share")
                ItemView(width: 100, height: 50, name: "Comments")
            }
            VStack {
                HStack {
                    ItemView(width: 50, height: 50, name: "1")
                    ItemView(width: 50, height: 50, name: "2")
                    ItemView(width: 50, height: 50, name: "3")
                    ItemView(width: 50, height: 50, name: "4")
                }
                HStack {
                    ItemView(width: 50, height: 50, name: "5")
                    ItemView(width: 50, height: 50, name: "6")
                    ItemView(width: 50, height: 50, name: "7")
                    ItemView(width: 50, height: 50, name: "8")
                }
                HStack {
                    ItemView(width: 50, height: 50, name: "9")
                    ItemView(width: 50, height: 50, name: "10")
                    ItemView(width: 50, height: 50, name: "11")
                    ItemView(width: 50, height: 50, name: "12")
                }
                HStack {
                    ItemView(width: 50, height: 50, name: "13")
                    ItemView(width: 50, height: 50, name: "14")
                    ItemView(width: 50, height: 50, name: "15")
                    ItemView(width: 50, height: 50, name: "16")
                }
                ItemView(width: 200, height: 50, name: "See more")
            }
            VStack {
                ItemView(width: 400, height: 100, name: "New feed #1")
                ItemView(width: 400, height: 200, name: "New feed #2")
                ItemView(width: 400, height: 100, name: "New feed #3")
                ItemView(width: 400, height: 500, name: "New feed #4")
            }
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity)
    }

Trong đó:

  • Bố cục cho màn hình chính là một ScrollView, vì ta đã xác định View của chúng ta sẽ dài hơn kích thước màn hình
  • Các View con sẽ chia ra nhiều block.
  • Với block đầu tiên, ta có 2 View xếp chồng lên nhau thì ta sử dụng ZStack
  • Tiếp theo, sử dụng HStack để bố cục 3 view trên 1 hàng
  • Block với dạng lưới thì kết hợp giữa VStack + HStack
  • Cuối cùng là theo dạng list (danh sách), ta sử dụng VStack

Để thấy được toàn bộ giao diện hiển thị ta sử dụng Live Preview. Bạn sẽ thấy View của chúng ta sẽ scroll được.

ScrollView Layout - SwiftUI

Scroll nhẹ 1 phát nữa nha!

Bây giờ, bạn dư sức chiến đấu để code Layout cho một project rồi nhoé!

6. Spacer

Cuối cùng, nó tuy nhỏ mà nó lại có võ. Đôi lúc, đây là cách bạn sẽ bố cục giao diện nhanh và gọn nhất. Ta lấy đoạn code block với “Like Share Comments” ở trên và thay đổi 1 chút với Spacer nha.

HStack {
    Spacer()
    ItemView(width: 100, height: 50, name: "Like")
    Spacer()
    ItemView(width: 100, height: 50, name: "Share")
    Spacer()
    ItemView(width: 100, height: 50, name: "Comments")
    Spacer()
}

Ta chèn các Spacer vào giữa các View. Công dụng của nó:

  • Sẽ giãn các View ra
  • Canh đều các khoảng cách giữa các View với nhau.

Bạn xem kết quả như sau:

Tạm kết

  • Họ hàng nhà Stack, sẽ bố cục các view theo các hướng
  • HStack là một view chứa các view con được sắp xếp theo chiều ngang
  • VStack là một view chứa các view con được sắp xếp theo chiều dọc
  • ZStack là một view chứa các view con được sắp xếp theo chiều trục Z, hay nói các khác các view có thể đè lên nhau từng lớp
  • ScrollView để hiển thị và cuộn với giao diện có kích thước lớn
  • Spacer để cách đều và giãn cách các View trong View cha

 

Okay! Tới đây, mình xin kết thúc bài viết này. 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!

FacebookTweetPinYummlyLinkedInPrintEmailShares41

Related Posts:

  • Tích hợp UIView (UIKit) vào SwiftUI Project - SwiftUI Notes #15
    Tích hợp UIView (UIKit) vào SwiftUI Project - SwiftUI Notes…
  • Cài đặt UIScrollView với Auto Layout trong Interface Builder
    Cài đặt UIScrollView với Auto Layout trong Interface Builder
  • SwiftUI - Phần 10 : Grid Layout
    SwiftUI - Phần 10 : Grid Layout
  • SwiftUI App Life Cycle - SwiftUI Notes #6
    SwiftUI App Life Cycle - SwiftUI Notes #6
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 api AppDistribution Asynchronous autolayout basic ios tutorial blog callback ci/cd closure collectionview combine concurrency CoreData Core Location crashlytics darkmode dart dart basic dart tour Declarative decoding delegate deploy fabric fastlane firebase flavor flutter GCD iOS mapview MVVM optional protocol rxswift Swift Swift 5.5 SwiftUI SwiftUI Notes tableview testing TravisCI unittest

Recent Posts

  • Raw String trong 10 phút
  • Dispatch Semaphore trong 10 phút
  • Tổng kết năm 2022
  • KeyPath trong 10 phút – Swift
  • Make color App Flutter
  • Ứng dụng Flutter đầu tiên
  • Cài đặt Flutter SDK & Hello world
  • Coding Conventions – người hùng hay kẻ tội đồ?
  • Giới thiệu về Flutter
  • Tìm hiểu về ngôn ngữ lập trình Dart

You may also like:

  • Basic Grid Layout - SwiftUI Notes #52
    Basic Grid Layout - SwiftUI Notes #52
  • Switching Grid Layout - SwiftUI Notes #55
    Switching Grid Layout - SwiftUI Notes #55
  • Basic TextField - SwiftUI Notes #27
    Basic TextField - SwiftUI Notes #27
  • RxCocoa Basic – Display Data from API
    RxCocoa Basic – Display Data from API
  • Cài đặt UIScrollView với Auto Layout trong Interface Builder
    Cài đặt UIScrollView với Auto Layout trong Interface Builder

Archives

  • 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 (22)
  • Code (4)
  • Combine (22)
  • Flutter & Dart (24)
  • iOS & Swift (86)
  • RxSwift (37)
  • SwiftUI (76)
  • Tutorials (70)

Newsletter

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

    Copyright © 2023 Fx Studio - All rights reserved.

    Share this ArticleLike this article? Email it to a friend!

    Email sent!