Khả năng tạo các công cụ sửa đổi chế độ xem tùy chỉnh là một tính năng mạnh mẽ trong SwiftUI. Trong bài viết này, chúng tôi sẽ đề cập đến các ví dụ về cách sử dụng tính năng này để giúp việc xây dựng giao diện người dùng trở nên dễ dàng hơn rất nhiều. Nếu bạn không quen thuộc với ViewModifiers trong SwiftUI và cách tạo tùy chỉnh, bạn có thể đọc về chúng tại đây
Mục tiêu của bài viết này là đề cập đến một số cách khác nhau để tạo các công cụ sửa đổi và kiểu tùy chỉnh trong SwiftUI và cách chúng có thể được sử dụng để xây dựng giao diện người dùng mang tính khai báo hơn trong khi vẫn đạt được kết quả cuối cùng rõ ràng và nhất quán.
Giao diện người dùng cuối cùng mà chúng tôi muốn xây dựng là:
Hãy xem xét tất cả các thành phần riêng lẻ trên màn hình:
Nếu bạn xây dựng màn hình này mà không có bất kỳ công cụ sửa đổi nào, mã sẽ giống như thế này:
struct ContentView: View { var body: some View { VStack (alignment: .leading) { Image("feature") .resizable() .aspectRatio(contentMode: .fill) .frame(minWidth: 0, maxWidth: .infinity) .frame(height: 220) .cornerRadius(12) .padding(.bottom, 12) Text("Custom ViewModifiers in SwiftUI are the best!") .foregroundColor(Color("titleTextColor")) .font(.system(size: 20, weight: .bold)) .padding(.bottom, 12) Text("Custom ViewModifiers in SwiftUI let you create resuable styles that can be applied to all your views") .foregroundColor(Color("bodyTextColor")) .font(.system(size: 14, weight: .medium)) Spacer() Button(action: { }) { Text("Label") .font(.system(size: 14, weight: .medium)) } .frame(minWidth: 0, maxWidth: .infinity) .padding(.horizontal, 10) .padding(.vertical, 12) .background(Color.blue) .foregroundColor(Color.white) .cornerRadius(12) } .padding(.all, 16) } }
Tạo kiểu cho một số thành phần (ví dụ: tiêu đề và văn bản chi tiết) sẽ phải được sao chép
Các thay đổi đối với một số kiểu dáng phổ biến (phần tử đệm, bán kính góc, v.v.) sẽ phải được thực hiện ở nhiều nơi
Giờ đây, bạn có thể giải quyết vấn đề này theo cách của UIKit bằng cách tạo chế độ xem tùy chỉnh, nhưng tôi không phải là người hâm mộ phương pháp này vì nó liên quan đến việc rời khỏi Chế độ xem tích hợp và khiến việc giới thiệu các thành viên mới trong nhóm trở nên khó khăn hơn. Một cách dễ dàng hơn là xác định một số công cụ sửa đổi chế độ xem phổ quát có thể được áp dụng thay cho chính các kiểu.
Hãy chia nhỏ kiểu dáng phổ biến mà chúng ta cần:
Hãy bắt đầu với bán kính góc:
struct CommonCornerRadius: ViewModifier { func body(content: Content) -> some View { content .cornerRadius(12) } }
Cái này khá đơn giản, nó cho phép chúng ta áp dụng bán kính góc chung cho các phần tử. Điều này giúp dễ dàng thay đổi kiểu ứng dụng trên toàn cầu mà không phải tạo Chế độ xem tùy chỉnh hoặc phải thực hiện nhiều thay đổi trên cơ sở mã.
struct FullWidthModifier: ViewModifier { func body(content: Content) -> some View { content .frame(minWidth: 0, maxWidth: .infinity) } }
Điều này làm cho chế độ xem toàn chiều rộng dễ triển khai hơn, không cần thêm .frame
theo cách thủ công nữa!
struct TitleTextModifier: ViewModifier { func body(content: Content) -> some View { content .foregroundColor(Color("titleTextColor")) .font(.system(size: 20, weight: .bold)) } } struct BodyTextModifier: ViewModifier { func body(content: Content) -> some View { content .foregroundColor(Color("bodyTextColor")) .font(.system(size: 14, weight: .medium)) } }
Điều này sẽ cho phép tạo kiểu văn bản phổ biến, thông thường bạn sẽ tạo các thành phần Văn bản tùy chỉnh hoặc các hàm tiện ích và thêm các thành phần giao diện người dùng thông qua mã.
extension Image { func aspectFill() -> some View { self .resizable() .aspectRatio(contentMode: .fill) } }
Được rồi, bạn hiểu rồi…đây không phải là công cụ sửa đổi chế độ xem tùy chỉnh mà là một tiện ích mở rộng đơn giản. Điều này là do ViewModifiers áp dụng cho Chế độ xem chung và một số chức năng như resizable
chỉ áp dụng cho hình ảnh, sử dụng kết hợp tiện ích mở rộng và công cụ sửa đổi tùy chỉnh sẽ giúp giải quyết vấn đề này.
struct FullWidthButtonStyle: ButtonStyle { func makeBody(configuration: Configuration) -> some View { configuration.label .fullWidth() .foregroundColor(Color.white) .font(.system(size: 14, weight: .medium)) .padding(.horizontal, 10) .padding(.vertical, 12) .background(configuration.isPressed ? Color.blue.opacity(0.2) : Color.blue) } } struct FullWidthButton: ViewModifier { func body(content: Content) -> some View { content .buttonStyle(FullWidthButtonStyle()) } }
Cuối cùng, đây là nút dành cho nút, lưu ý rằng mặc dù chúng ta có thể chỉ cần tạo một ViewModifier để đạt được hiệu ứng tương tự nhưng giao diện của nút sẽ không thay đổi khi chạm vào. Điều này là do cài đặt .background
trên một nút buộc nó phải sử dụng nền đó ở cả trạng thái đã khai thác và chưa khai thác. ButtonStyle
cho phép chúng tôi thay đổi độ mờ của nút dựa trên việc nút đó có được nhấn hay không.
Bây giờ để thuận tiện, tôi muốn tạo các tiện ích mở rộng sử dụng các công cụ sửa đổi này:
extension View { func commonCornerRadius() -> some View { modifier(CommonCornerRadius()) } func fullWidth() -> some View { modifier(FullWidthModifier()) } func title() -> some View { modifier(TitleTextModifier()) } func body() -> some View { modifier(BodyTextModifier()) } func fullWidthButton() -> some View { modifier(FullWidthButton()) } } extension Image { func aspectFill() -> some View { self .resizable() .aspectRatio(contentMode: .fill) } }
struct ContentView: View { var body: some View { VStack (alignment: .leading) { Image("feature") .aspectFill() .fullWidth() .frame(height: 220) .commonCornerRadius() .padding(.bottom, 12) Text("Custom ViewModifiers in SwiftUI are the best!") .title() .padding(.bottom, 12) Text("Custom ViewModifiers in SwiftUI let you create resuable styles that can be applied to all your views") .body() Spacer() Button(action: { }) { Text("Awesome") } .fullWidthButton() .commonCornerRadius() } .padding(.all, 16) } }
Sạch sẽ hơn nhiều! Thoạt nhìn, điều này giống như nhiều mã và công sức hơn là chỉ thiết lập các kiểu theo cách thủ công nhưng về lâu dài, điều này sẽ tiết kiệm rất nhiều công sức. Về mặt cá nhân, phương pháp này cũng khuyến khích phong cách ứng dụng của bạn nhất quán hơn bằng cách dựa nhiều hơn vào các công cụ sửa đổi phổ biến hơn là dựa trên cơ sở kiểu dáng theo từng lượt xem.
Và đó là về nó! Hy vọng rằng điều này sẽ giúp bạn xây dựng ứng dụng của mình nhanh hơn và dễ dàng hơn, một lợi ích khác là những công cụ sửa đổi này có thể được đưa vào bất kỳ ứng dụng nào của bạn và được điều chỉnh để phù hợp với các nguyên tắc về phong cách của ứng dụng đó. Tôi cũng đang làm việc trên một thư viện để phát triển điều này hơn nữa, bạn có thể kiểm tra nó tại đây (PS: Tại thời điểm viết thư này, thư viện đang ở giai đoạn siêu sớm, repo trống: p nhưng hãy chú ý theo dõi)
Cũng được xuất bản ở đây.