Contents
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 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 conspacing
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!
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.
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.
Cảm ơn bạn đã đọc bài viết này!
Related Posts:
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
Fan page
Tags
Recent Posts
- Charles Proxy – Phần 1 : Giới thiệu, cài đặt và cấu hình
- Complete Concurrency với Swift 6
- 300 Bài code thiếu nhi bằng Python – Ebook
- Builder Pattern trong 10 phút
- Observer Pattern trong 10 phút
- Memento Pattern trong 10 phút
- Strategy Pattern trong 10 phút
- Automatic Reference Counting (ARC) trong 10 phút
- Autoresizing Masks trong 10 phút
- Regular Expression (Regex) trong Swift
You may also like:
Archives
- 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)