【SwiftUI】modifier(モディファイア)の自作方法!カスタムモディファイア
この記事からわかること
- SwiftUIのmodifier(モディファイア)とは?
- モディファイアを自作する方法
- カスタムモディファイアとは?
- ViewModifierプロトコルとは?
- 通常のモディファイアのように呼び出す方法
- 引数を持たせる方法
index
[open]
\ アプリをリリースしました /
友達や家族の誕生日をメモ!通知も届く-みんなの誕生日-
posted withアプリーチ
SwiftUIでTextやVStackなどのView構造体を変化させるために使用するmodifier(モディファイア)を自作する方法をまとめました。
modifierメソッドとは?
font
やpadding
など数あるモディファイアですが、大元となっているのはViewプロトコルに定義されているmodifierメソッドです。SwiftUIではこのメソッドを拡張してさまざまなモディファイアが定義されています。
protocol View {
var body: Self.Body
func modifier<T>(_ modifier: T) -> ModifiedContent<Self, T>
}
この状態を理解した上でカスタムモディファイアの作成に移っていきたいと思います。
modifier(モディファイア)を自作する方法
流れ
- ViewModifierに準拠した構造体を作成
- modifierメソッドで呼び出す
モディファイアを自作するには構造体の作成が必要になります。この構造体にカスタムのモディファイアを作っていくのですが、0から作るというよりも既存のモディファイアをあらかじめ組み合わせて置いて再利用しやすいように作るのが目的になります。
また作成の手順は公式リファレンスにも掲載されているのでそちらも参考にしてください。
ViewModifierに準拠した構造体を作成
まずはViewModifier
プロトコルに準拠させた構造体を定義します。準拠させるためにはbody
メソッドの定義が必要になります。その引数から実際にモディファイアを適応させるContent
が受け取れるので、Content
に対して以下のようにモディファイアを列挙していきます。
struct BlackBackCyanText: ViewModifier {
func body(content: Content) -> some View {
content
.font(.title)
.padding(10)
.foregroundColor(.cyan)
.background(.black)
.cornerRadius(5)
}
}
これでカスタムモディファイアの定義が完了しました。続いてこれを実際にText構造体などに使用する方法をみていきます。
modifierメソッドで呼び出す
カスタムモディファイアを適応させるにはmodifier
メソッドの引数にカスタムモディファイアをインスタンス化するだけです。
struct ContentView: View {
var body: some View {
VStack{
Text("Hello")
.modifier(BlackBackCyanText())
Text("World")
.modifier(BlackBackCyanText())
}
}
}
カスタムモディファイアを使用することで上記のように複数のビューに対して同じデザインを簡単に使い回すことが可能になります。
しかしこれではまだmodifier
メソッドを呼び出すのが冗長的です。これをpadding
などと同じような形で呼び出すようにしていきたいと思います。
modifierメソッドを使わずに通常のように呼び出す
以下のような形で呼び出せるようにするにはViewを拡張していきます。
struct ContentView: View {
var body: some View {
VStack{
Text("Hello")
.blackBackCyanText()
Text("World")
.blackBackCyanText()
}
}
}
以下のようにViewを拡張して中に新しくメソッドを増やしていきます。このメソッド名が実際にモディファイアとして付与することになる修飾名になります。
extension View {
func blackBackCyanText() -> some View {
modifier(BlackBackCyanText())
}
}
引数を持たせる
カスタムモディファイアでは引数を持たせることも可能です。これによりカラーだけを変えたり、サイズだけを変えると言った使い回しがしやすくなります。引数を持たせるには定義したViewModifier構造体にプロパティを持たせます。
// MARK: - 丸型背景色
struct BackRoundColor: ViewModifier {
let backgroundColor: Color
func body(content: Content) -> some View {
content
.frame(width: 40, height:40)
.background(backgroundColor)
.foregroundColor(.white)
.cornerRadius(50)
.compositingGroup()
.shadow(color: .gray,radius: 3, x: 2, y: 2)
}
}
extension View {
func BackRoundColor(color:Color) -> some View {
modifier(プロジェクト名.BackRoundColor(backgroundColor: color))
}
}
Imageなど限定のモディファイアを含んだカスタムモディファイアの作り方
Image
構造体の持つresizable
など、特定のViewしか持たないモディファイアを含んだカスタムモディファイアを定義したい場合は上記の方法ではなく、そのViewを拡張(extension
)してカスタムモディファイアを定義します。
extension Image {
func ex_ResizableTopIconModifier() -> some View {
self
.resizable(resizingMode: .stretch)
.frame(width: 200, height: 150)
.padding(.bottom,145)
.foregroundColor(Color.white)
}
}
まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。
ご覧いただきありがとうございました。
私がSwift UI学習に使用した参考書