カスタム ビュー修飾子を作成する機能は、SwiftUI の強力な機能です。この記事では、この機能を使用して UI の構築を非常に簡単にする方法の例を取り上げます。 SwiftUIの ViewModifiers とカスタムのものを作成する方法に慣れていない場合は、ここでそれらについて読むことができます
この記事の目的は、SwiftUI でカスタム モディファイアとスタイルを作成するさまざまな方法と、それらを使用して UI をより宣言的に構築しながら、クリーンで一貫性のある最終出力を実現する方法について説明することです。
構築する最終的な UI は次のとおりです。
画面上の個々のコンポーネントをすべて考えてみましょう。
この画面を修飾子なしで作成すると、コードは次のようになります。
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) } }
一部の要素 (タイトルや詳細テキストなど) のスタイル設定を複製する必要があります。
一般的なスタイリング (要素のパディング、角の半径など) の一部を変更するには、複数の場所で行う必要があります。
カスタムビューを作成することでUIKitの方法でこの問題を解決できますが、私はこのアプローチのファンではありません.もっと簡単な方法は、スタイル自体の代わりに適用できるいくつかのユニバーサル ビュー修飾子を定義することです。
必要な一般的なスタイリングを分解してみましょう。
角の半径から始めましょう:
struct CommonCornerRadius: ViewModifier { func body(content: Content) -> some View { content .cornerRadius(12) } }
これはかなり単純で、要素にユニバーサル コーナー半径を適用できます。これにより、カスタム ビューを作成したり、コードベース全体で複数の変更を行ったりすることなく、アプリ スタイルをグローバルに簡単に変更できます。
struct FullWidthModifier: ViewModifier { func body(content: Content) -> some View { content .frame(minWidth: 0, maxWidth: .infinity) } }
これにより、全幅ビューの実装が簡単になり、手動で.frame
を追加する必要がなくなります!
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)) } }
これにより、一般的なテキスト スタイルが可能になります。通常は、カスタム テキスト コンポーネントまたはユーティリティ関数を作成し、コードを使用して UI コンポーネントを追加します。
extension Image { func aspectFill() -> some View { self .resizable() .aspectRatio(contentMode: .fill) } }
わかりました。これはカスタム ビュー修飾子ではなく、単純な拡張機能です。これは、ViewModifiers がジェネリック ビューに適用され、 resizable
などの一部の機能が画像にのみ適用されるためです。拡張機能とカスタム修飾子を組み合わせて使用すると、これを回避できます。
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()) } }
最後に、これはボタンの場合です。単純に ViewModifier を作成して同じ効果を実現することもできますが、タップしてもボタンの外観は変わらないことに注意してください。これは、ボタンに.background
を設定すると、タップされた状態とタップされていない状態の両方でその背景を使用するように強制されるためです。 ButtonStyle
ボタンが押されているかどうかに基づいてボタンの不透明度を変更できます。
便宜上、これらの修飾子を使用する拡張機能を作成するのが好きです。
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) } }
もっときれいに!一見すると、スタイルを手動で設定するよりも多くのコードと労力がかかるように思えますが、長い目で見れば、これにより多くの労力が節約されます。個人的には、このアプローチは、ビューごとのスタイリングよりも共通の修飾子に依存することで、アプリのスタイルをより一貫性のあるものにすることも奨励します。
そしてそれはそれについてです!これにより、アプリをより迅速かつ簡単に構築できるようになることを願っています。もう 1 つの利点は、これらの修飾子を任意のアプリにドロップして、スタイル ガイドラインに合わせて微調整できることです。私はまた、これをさらに進めるためにライブラリに取り組んでいます。ここで確認できます (PS: これを書いている時点では、ライブラリは非常に初期の段階にあり、レポは空です :p ですが、お楽しみに)