Contents
Chào mừng bạn đến với Fx Studio và hành trình của series SwiftUI Notes bất tận này. Bài viết này sẽ tập trung vào một đối tượng View cơ bản mà có mặt ở hầu hết các nền tảng. Đó là Image View (hay gọi là Image) trong SwiftUI.
Nếu mọi thứ đã ổ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:
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.)
Image View
An image is worth a thousand words.
Image chính là cách mà bạn có thể truyền tải đi rất nhiều thông điệp bằng một cách đơn giản nhất. Vì vậy, trong giao diện bạn nên tận dụng chúng một cách tối đa nhất. Và Image cũng là một thành phần không thể nào thiếu được trong bất cứ thiết kế UI nào cho bất kì nền tảng nào.
Trong SwiftUI, đối tượng hiển thị cho một hình ảnh là Image
. Chắc bạn cũng quá quen thuộc với nó rồi và như trước đây với iOS chúng ta có UIImageView
vậy. Hình ảnh có thể lấy được từ nhiều nguồn. Ví dụ:
- Các ảnh được lưu trữ thành tài nguyên trong Assets
- Các đối tượng từ các nền tảng khác của Apple như
NSImage
vàUIImage
- Một ảnh dưới dạng
bitmap
được thể hiện bằngCGImage
của Core Graphics - Những icon & ảnh hệ thống, trong bộ sưu tập
SF Symbols
- …
Và bây giờ, chúng ta sẽ bắt đầu tìm hiểu xem Image trong SwiftUI như thế nào và có gì đặc biệt nha.
1. Display Image
Mọi việc bắt đầu bằng hiển thị một ảnh. Chúng ta sẽ sử dùng 2 nguồn chính, đó là lưu trữ trong Assets và ảnh hệ thống. Các nguồn khác như từ một URL nào đó hay ảnh động thì chúng ta sẽ bàn ở một bài viết khác nha.
1.1. Assets
Trước tiên, bạn hãy tạo mới một file SwiftUI View, đặt tên gì cũng được. Chúng ta sẽ có code mặc định được tạo kèm với file đó. Bạn hãy thay Text bằng Image, theo ví dụ sau:
var body: some View { Image("cat") }
Trong đó, mình sử dụng 1 ảnh được lưu trong file Assets.xcassets
. Cú pháp của Image thì khá là đơn giản, tham số là String, tên của ảnh được lưu trong Assets.
Bạn bấm Resume và xem kết quả Preview nha!
Sử dụng hình mèo cho tăng tương tác thôi. Ahihi!
1.2. SF Symbols
Hình ảnh hay các icon trong hệ thống, thì được Apple cung cấp. Với việc bạn chỉ cần download thêm bộ sưu tập SF Symbol, thì bạn có trong tay hơn 1000 icon khác nhau các loại. Và đôi khi chúng ta gọi nó là ảnh hệ thống.
(Link download tại đây)
Bạn sẽ tiết kiệm đi rất nhiều thời gian cho việc thiết kế ứng dụng của mình, bằng cách tận dụng những icon này. Và ưu điểm của chúng nó là dưới dạng vector
nên bạn có thể thoải mái về kích thước cho các icon này mà không sợ vỡ hình.
Bạn hãy tìm 1 cái tên trong đám icon đó, và sửa lại đoạn code trên như sau:
Image(systemName: "tornado")
Để hiển thị ảnh hệ thống, ta chọn hàm khởi tạo Image với tham số label là systemName
là được. Xem thử nó hiển thị như thế nào.
Bạn sẽ thấy cái hình nhỏ xí xi ở chính giữa màn hình đó. Để cho nó to lên thì chúng ta sẽ đi qua phần tiếp theo.
2. Change size
Đây chính là điều khó chịu đầu tiên khi bạn sử dụng Image View trong SwiftUI. Đó chính là kích thước của Image. Bạn hãy xem lại ví dụ hình mèo dễ thương của mình.
Cái viền màu xanh là biểu thị cho kích thước thật của ảnh chúng ta. Nó khá là lớn so với màn hình điện thoại. Chúng ta sẽ fix nó ngay thôi.
2.1. Resize-able
Sai lầm thứ 2 nữa của chúng ta hay quên đi. Đó là
Tất cả chỉ là View
Với hình trên, nó không phải kích thước View là kích thước màn hình. Mà màn hình điện thoại đó chỉ là khung hình để xem mà thôi. Nó không liên quan gì tới kích thước của Image.
Sau khi đọc qua 2 sai lầm cơ bản. Thì công việc của bạn chỉ còn là biến:
Image từ không thể thay đổi kích thước thành có thể thay đổi được kích thước
Bạn chỉ cần thêm một modifier .resizable()
vào sau Image là ổn.
Image("cat") .resizable()
Xem kết quả nào!
Với tính năng đó thì ảnh của bạn sẽ auto resize vừa với kích thước chứa của View.
2.2. Tiled resizing
Một trò khá là vui cho Image View đến từ SwiftUI. Bạn hãy tìm một ảnh với kích thước nhỏ, và dùng đoạn code sau để hiển thị chúng.
Image("star") .resizable(resizingMode: .tile)
Trong đó,
star
là ảnh với kích thước 50x50px- Vẫn là việc resize nhưng với kích thước ảnh nhỏ hơn View chưa thì sẽ dùng chế độ lặp lại nó
- Sử dụng tham số
resizingMode: .tile
để fill ngôi sao đó cho toàn bộ màn hình
Xem kết quả nào!
Khá là đẹp cho Image View phải không nào, bạn nào có ý tưởng làm các background cute thì chừ quá đơn giản rồi đó.
Ngoài ra, với Tiled resizing này còn có nhiều tham số nữa, bạn hãy tự khám phá thêm nha. Ví dụ như sau, để thay đổi index của ảnh sao cho đẹp nhất với từng vị trí xác định.
.resizable( capInsets: .init( top: 30, leading: 30, bottom: 30, trailing: 30 ), resizingMode: .tile )
2.3. Scale
Bạn nhìn lại hình mèo dễ thương ở trên sau khi resize, bạn cũng cảm nhận ảnh bị bóp méo đi. Vậy muốn ảnh đẹp hơn thì chúng ta cũng phải chọn đúng chế độ khi scale
ảnh. Và bạn có 2 chế độ cơ bản sau:
fit
Ta lại có 2 cách dùng với chế độ fit
. Bạn tham khảo code sau:
Image("cat") .resizable() .aspectRatio(contentMode: .fit)
Hoặc
Image("cat") .resizable() .scaledToFit()
Xem kết quả mèo dễ thương nào!
fill
Với chế độ fill
cũng tương tự, ta cũng có 2 cách để sử dụng chế độ này
Image("cat") .resizable() .aspectRatio(contentMode: .fit)
Hoặc
Image("cat") .resizable() .scaledToFill()
Xem kết quả mèo dễ thương nào!
Tuy nhiên, với modifier .aspectRatio
bạn sẽ có nhiều khám phá hơn. Không chỉ là 2 chế độ đơn giản như vậy.
Ví dụ: ta sử dụng tỉ lệ scale cho 2 kích thước của ảnh như sau:
Image("cat") .resizable() .aspectRatio(0.7, contentMode: .fill)
Kết quả nè!
Khung hình màu xanh đã nhỏ đi khá nhiều rồi.
2.4. Frame
Nếu như tất cả vẫn chưa thỏa mãn được bạn và bạn vẫn muốn Image View có một kích thước xác định nào đó. Thì hãy sử dụng:
- Modifier
.frame
để xác định kích thước - SwiftUI đủ thông minh để có thể tính toán các tham số kích thước, ngay khi bạn cung cấp không đầy đủ tham số truyền vào.
- Xác định
width
hayheight
hay cả 2 đều được - Xác định kích thước
min
haymax
cho 2 chiều
Tham khảo code ví dụ cho mèo dễ thương tiếp nha.
Image("cat") .resizable() .scaledToFit() .frame(width: 300)
Lúc này mèo dễ thương trông nhỏ nhắn xinh đẹp rồi!
3. Full screen & Safe area
3.1. Full screen
Tới đây, nhiều bạn cùng gặp chung một vấn đề là: “làm thế nào để ảnh full màn hình?”. Khi mà SwiftUI rất linh hoạt và có thể build được lên nhiều thiết bị. Do đó, việc xác định kích thước màn hình chính xác thì rất khó. Bên cạnh đó …
Chúng ta đã nói lời chia tay với AutoLayout rồi. Ahuhu!
Nhưng mà ông trời không tuyệt đường sống của ta bao giờ. Khi Apple cung cấp cho bạn một giá trị là .infinity
để dùng làm đối số truyền vào cho các tham số width
& height
trong modifier .frame
. Bạn thử xem đoạn code sau với mèo dễ thương nha.
Image("cat") .resizable() .frame(width: .infinity, height: .infinity)
Kết quả ra như sau nhoé!
3.2. Safe area
Mình đã cố tình sử dụng simulator là iPhone 12 để cho có phần tai thỏ. Và bạn cũng dễ dàng thấy được 2 khoảng trắng 2 đầu rồi.
Nguyên nhân chính là Safe area của các đời iPhone X. Đây là vùng an toàn để bạn thiết kế giao diện. Với AutoLayout bạn cũng phải kéo thả constraint và ràng buộc chúng với Safe area. Thì SwiftUI cũng như vậy.
Để giúp bạn thoả mãn 100%, thì chúng ta sẽ bỏ qua phần Safe area này, bạn chỉ cần thêm modifier .ignoresSafeArea()
vào là mọi thứ ổn ngay.
Image("cat") .resizable() .ignoresSafeArea() .frame(width: .infinity, height: .infinity)
Ở trên, mình thêm vào đoạn code ví dụ mèo dễ thương. Kết quả sẽ như thế này nè!
Hài lòng mọi người chưa!
4. Image as a backgrounds
Một công dụng phải nói nhức nách nữa của Image chính là làm hình nền. Vì hầu như mọi developer đều đã sử dụng ảnh làm background cho View, Button, NavigationBar … Do đó, mình xin mạn phép đưa vào luôn bài viết này.
Ngoài ra, cũng giúp cho các bạn thấy được sự đa năng của SwiftUI như thế nào. Khi mà background nó cũng xem là một View. Bạn có thể làm mọi thứ với nó. Xem ví dụ code mèo dễ thương tiếp là được.
HStack { Text("Mèo dễ thương! Moa moa") .font(.largeTitle) .fontWeight(.heavy) .foregroundColor(Color.white) } .background( Image("cat") .resizable() .scaledToFill() .edgesIgnoringSafeArea(.all) .frame(width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height) )
Trong đó:
- Đối tượng chính là một Text
- Tại modifier
.background
ta cung cấp cho nó là một Image - Tuỳ theo sở thích của bạn mà bạn tuỳ biến Image đó thành một Background đẹp cho Text
Bạn xem kết quả nhoé!
5. Make color
Chúng ta sang phần làm màu cho đối tượng Image nào. Lưu ý, đây chỉ là những modifier hay sử dụng mà thôi. Chứ không phải là tất cả nha. Mục đích là giúp bạn tham khảo một tí.
Chúng ta sẽ bắt đầu từ đoạn code này nha.
Image("cat") .resizable() .frame(width: 300, height: 300)
5.1. cornerRadius
Đây cũng là một trong các modifier phổ biến nhất. Bạn sử dụng .cornerRadius
để bo tròn một View hay Image View. Code ví dụ như sau:
Image("cat") .resizable() .frame(width: 300, height: 300) .cornerRadius(30.0)
Xem kết quả nhoé!
Còn bạn muốn cho Image của bạn thành hình tròn thì sử dụng cứ truyền cho tham số của .cornerRadius
với một nữa của width
là đẹp ngay.
Image("cat") .resizable() .frame(width: 300, height: 300) .cornerRadius(150.0)
Xem tiếp kết quả mèo dễ thương nha!
5.2. overlay
Modifier .overlay
thì bạn có thể thêm những nội dung lên trên đối tượng View. Và Image View cũng không ngoại lệ. Sẽ rất thú vị, SwiftUI khá linh hoạt phải không nào. Bạn có thể thêm bất cứ View nào vào cũng được.
Xem code ví dụ với việc sử dụng .overlay
cho Image là một Text nha.
Image("cat") .resizable() .frame(width: 300, height: 300) .cornerRadius(30.0) .overlay( Text("Mèo dễ thương") .foregroundColor(Color.white) .padding([.bottom, .trailing], 10) .opacity(0.8), alignment: .bottomTrailing )
Trong đó
- Content của
.overlay
chính là một Text - Cần thêm tham số
alignment
để xác định vị trí củaoverlay
.bottomTrailing
sẽ là góc dưới bên phải của View- Các modifier khác bạn tự tìm hiểu nha, cũng không quá khó lắm
Bạn xem kết quả nhoé!
5.3. background
Modifier .background
thì quá bình thường rồi. Bạn sẽ phủ màu hoặc cái gì đó làm hình nền cho Image. Nó có tác dụng khi ảnh của bạn trong suốt. Hoặc khi bạn load ảnh từ một URL nào nó, trong lúc chờ kết nối mạng …. cũng rất nhiều ứng dụng với modifier này.
Còn bây giờ, bạn xem qua code ví dụ với mèo dễ thương ở trên nha. Mình có thay đổi giá trị radius để bo tròn lớn hơn. Giúp bạn nhìn rõ đc background color.
Image("cat") .resizable() .frame(width: 300, height: 300) .cornerRadius(50.0) .overlay( Text("Mèo dễ thương") .foregroundColor(Color.white) .padding([.bottom, .trailing], 10) .opacity(0.8), alignment: .bottomTrailing ) .background(Color.green)
Xem kết quả luôn nhoé!
5.4. clipShape
Modifier .clipShape
này sẽ cắt Image của chúng ta theo 1 hình dạng nào đó mà ta cung cấp. Mình sẽ thực hiện với hình cắt là hình tròn cho Image ở trên. Xem ví dụ code nào.
Image("cat") .resizable() .frame(width: 300, height: 300) .cornerRadius(50.0) .overlay( Text("Mèo dễ thương") .foregroundColor(Color.white) .padding([.bottom, .trailing], 10) .opacity(0.8), alignment: .bottomTrailing ) .background(Color.green) .clipShape(Circle())
Khá là đơn giản khi truyền tham số là một đối tượng Circle()
. Xem kết quả nhoé!
5.5. foregroundColor
Cái này áp dụng cho các Image hệ thống nha. Nó như tintColor
vậy. Bạn có thể xét màu của Image View giống như màu chữ của Text thông qua modifier .foregroundColor
. Rất nhanh và rất tiện lợi!
Bạn xem ví dụ mới của mình như sau:
VStack { Image(systemName: "star") .resizable() .frame(width: 80.0, height: 80.0) .foregroundColor(.blue) Image(systemName: "star") .resizable() .frame(width: 80.0, height: 80.0) .foregroundColor(.green) Image(systemName: "star") .resizable() .frame(width: 80.0, height: 80.0) .foregroundColor(.red) Image(systemName: "star") .resizable() .frame(width: 80.0, height: 80.0) .foregroundColor(.orange) Image(systemName: "star") .resizable() .frame(width: 80.0, height: 80.0) .foregroundColor(.yellow) }
Sử dụng Image hệ thống, với đầy đủ màu sắc khác nhau cho mỗi Image. Xem kết quá nhoé!
Tạm kết
Qua trên, mình đã trình bày những thứ cơ bản liên quan tới Image của SwiftUI. Và chúng chỉ mang tính chất cơ bản mà thôi. Quan trọng bạn cần nhớ đến modifier .resizable()
là được. Vì tất cả các thao tác tới Image sẽ chính xác hơn khi Image có thể thay đổi được kích thước.
Okay! Tới đây, mình xin kết thúc bài viết về đối tượng Image 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.
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
- Prompt Engineering trong 10 phút
- Một số ví dụ sử dụng Prompt cơ bản khi làm việc với AI
- Prompt trong 10 phút
- 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
You may also like:
Archives
- December 2024 (3)
- 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)