paint-brush
Hướng dẫn cần thiết về SwiftUI: Giao diện người dùng có thể tái sử dụng với Công cụ sửa đổi tùy chỉnhtừ tác giả@nemi
1,615 lượt đọc
1,615 lượt đọc

Hướng dẫn cần thiết về SwiftUI: Giao diện người dùng có thể tái sử dụng với Công cụ sửa đổi tùy chỉnh

từ tác giả Nemi Shah9m2023/04/28
Read on Terminal Reader

dài quá đọc không nổi

Chế độ xem tùy chỉnh trong SwiftUI cho phép bạn tạo các kiểu có thể thay thế được có thể áp dụng cho tất cả các chế độ xem của bạn. 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. 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 Swift UI.
featured image - Hướng dẫn cần thiết về SwiftUI: Giao diện người dùng có thể tái sử dụng với Công cụ sửa đổi tùy chỉnh
Nemi Shah HackerNoon profile picture
0-item
1-item

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:

  • Hình ảnh: Một thành phần hình ảnh tiêu chuẩn với một số bán kính góc
  • Văn bản: Chúng tôi có một tiêu đề và một văn bản cơ thể
  • Nút: Nút có chiều rộng đầy đủ

Mã SwiftUI đơn giản

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) } }


Có một số vấn đề với cách tiếp cận này:

  • 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:

  • Bộ chứa màn hình: Bản thân màn hình có phần đệm chung, đây là tùy chọn nhưng tôi thích tất cả các màn hình đều có kiểu chung
  • Bán kính góc
  • Tiêu đề và nội dung văn bản
  • Chiều rộng đầy đủ: Các mục cần có thể lấp đầy chiều rộng của mục gốc (nút và hình ảnh trong ví dụ trên)
  • Kiểu nút
  • Chia tỷ lệ hình ảnh

Công cụ sửa đổi chế độ xem tùy chỉnh

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) } }


Bây giờ, hãy chuyển đổi mã để sử dụng chúng thay vì tạo kiểu trực tiếp:


 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.