【SwiftUI】TextField の角を丸くして背景色を付けるもっとも簡単な方法は

これ簡単に作る方法ありませんかね。

角の丸い背景に色を付けた TextField。

なんか簡単にできないんですが、

いい方法ありませんか。

 

🧑‍💻 やってみる

「角を丸く」

「背景色を黄色に」

が同時にできません。


TextField("Search", text: $text)
  .frame(width: 200)
  .background(.yellow)

TextField("Search", text: $text)
  .frame(width: 200)
  .textFieldStyle(.roundedBorder)
  .background(.yellow) // NG
  .backgroundStyle(.yellow) // NG
  .tint(.yellow) // NG

👉 roundedBorder | Apple Developer Documentation hatena-bookmark

 

🧑‍💻 Chain Modifiers

一度、スタイルを plain にして、

padding を付けて、

背景に黄色い角丸四角を置きます。


// chain view modifiers
TextField("Search", text: $text)
  .textFieldStyle(.plain)
  .padding(6)
  .background(.yellow, in: .rect(cornerRadius: 6))
  .frame(width: 200)

しかし、数行続くと View 全体の見通しが悪くなるのがいやだ。

 

🧑‍💻 Create TextFieldStyle

TextField 専用のスタイルを作ってそれを適用します。


struct RoundedBordertFieldStyle: TextFieldStyle {
  var cornerRadius: CGFloat
  var color: Color

  func _body(configuration: TextField<Self._Label>) -> some View {
    configuration
      .textFieldStyle(.plain) // macOS
      .padding(cornerRadius)
      .background(color, in: .rect(cornerRadius: cornerRadius))
  }
}

extension TextFieldStyle where Self == RoundedBordertFieldStyle {
  static var roundedBorderYellow: Self {
    Self(cornerRadius: 6, color: .yellow)
  }
}


TextField("Search", text: $text)
  .textFieldStyle(RoundedBordertFieldStyle(cornerRadius: 6, color: .yellow)) // OK
  //.textFieldStyle(.roundedBorderYellow) // OK
  .frame(width: 200)

しかし、いちいちここまで書くのがいやだ。

_ (アンダースコア) もなんかいや。

👉 TextFieldStyle Protocol "makeBody" method hidden | Apple Developer Forums hatena-bookmark

 

🧑‍💻 Create View extension

ViewModifier を作ろうかと思ったが、

View の extension まででいいですよね。


extension View {
  func roundedBorder(cornerRadius: CGFloat, color: Color) -> some View {
    self
      .textFieldStyle(.plain)
      .padding(cornerRadius)
      .background(color, in: .rect(cornerRadius: cornerRadius))
  }
}


// create view extension (or view modifier)
TextField("Search", text: $text)
  .roundedBorder(cornerRadius: 6, color: .yellow)
  .frame(width: 200)

これぐらいがいいのかな。

 

🧑‍💻 Create Child View

新しく View を作って、それに押し込んじゃいます。


struct RoundedBorderTextField: View {
  var label: String
  @Binding var text: String
  var cornerRadius: CGFloat
  var color: Color

  var body: some View {
    TextField(label, text: $text)
      .textFieldStyle(.plain)
      .padding(cornerRadius)
      .background(color, in: .rect(cornerRadius: cornerRadius))
  }
}


// create child view
RoundedBorderTextField(label: "Search", text: $text, cornerRadius: 6, color: .yellow)
  .frame(width: 200)

最初からこれで良かったのでは。

 

🧑‍💻 まとめ

どれが一番いいんすかね。

macOS に切り替えなが思ったのは、

実際、TextField って、

「フォーカス」とかも

取り扱ってますよね。

それを考えると、

「@State を考慮してるやつ」

のがいいのかもしれません。

👉 【SwiftUI】市松模様を背景にする - Checkered Pattern Background 🏁 hatena-bookmark
👉 【SwiftUI】枠線付き角丸ボタンを簡単に作りたい hatena-bookmark



【SwiftUI】Color とは一体何なのか

ふと思ったのですが。


Color
  .red
  .frame(width: 200, height: 200)

ただの「色」なのに、

「縦横寸法が指定できる」

「枠や対象がないのに表示される」

なんだか気持ち悪くないですか。

一体何者なんだ。

 

🎨 何者であるかの種類

思いつくものを、いくつか挙げておきます。

このうちのどれかだと思います。

View
A type that represents part of your app’s user interface and provides modifiers that you use to configure views.
アプリのユーザーインターフェイスの一部を表し、ビューの設定に使用する修飾子を提供するタイプ。

👉 View | Apple Developer Documentation hatena-bookmark

Shape
A 2D shape that you can use when drawing a view.
ビューを描くときに使用できる2D形状。

👉 Shape | Apple Developer Documentation hatena-bookmark

ShapeStyle
A color or pattern to use when rendering a shape.
図形をレンダリングするときに使用する色またはパターン。

👉 ShapeStyle | Apple Developer Documentation hatena-bookmark

眺めてるとなんとなくわかります。

何者かの種類のことが

「Protocol」

だったのですね !

 

🎨 よく使うあれは何者なのか

ドキュメントの「Conforms To」のところを見ます。

よく使うやつを見てみます。

Text
A view that displays one or more lines of read-only text.


Conforms To
Equatable
Sendable
View // *

👉 Text | Apple Developer Documentation hatena-bookmark

→ Text は View。

Button
A control that initiates an action.


Conforms To
View // *

👉 Button | Apple Developer Documentation hatena-bookmark

→ Button は View。

VStack
A view that arranges its subviews in a vertical line.


Conforms To
View // *

👉 VStack | Apple Developer Documentation hatena-bookmark

→ VStack は View。

Circle
A circle centered on the frame of the view containing it.


Conforms To
Animatable
ChartSymbolShape
InsettableShape
Sendable
Shape // *
View // *

👉 Circle | Apple Developer Documentation hatena-bookmark

→ Circle は Shape であり、View でもある。

RoundedRectangle
A rectangular shape with rounded corners, aligned inside the frame of the view containing it.


Conforms To
Animatable
InsettableShape
Sendable
Shape // *
View // *

👉 RoundedRectangle | Apple Developer Documentation hatena-bookmark

→ RoundRectangle は Shape であり、View でもある。

Material
A background material type.


Conforms To
Sendable
ShapeStyle // *

👉 Material | Apple Developer Documentation hatena-bookmark

→ Material は ShapeStyle である。

では、

Color
A representation of a color that adapts to a given context.


Conforms To
CustomStringConvertible
Equatable
Hashable
Sendable
ShapeStyle // *
Transferable
View // *

👉 Color | Apple Developer Documentation hatena-bookmark

→ Color は、 ShapeStyle であり、View でもある !

 

🎨 まとめ

Color は、

Material のような塗りつぶし方法の「ShapeStyle」であり、

Text のような表示の具の 「View」 でもある。

だったのだ !

👉 The many faces of ShapeStyle in SwiftUI | Swift with Majid hatena-bookmark
👉 Every SwiftUI protocol explained | FIVE STARS hatena-bookmark


【SwiftUI】CardView のような GroupBox は本当に便利なのか

こういうやつが簡単に作れる。

👉 GroupBox | Apple Developer Documentation hatena-bookmark


GroupBox("Today's Menu") {
  VStack(alignment: .leading) {
    Text("🍛 curry and rice")
    Text("🥗 green salad")
  }
}
.frame(width: 300)

 

🧑🏻‍💻 作ってみた

手作りと比較します。




VStack {
  HStack {
    Text("Today's Menu")
      .bold()
    Spacer()
  }
  VStack(alignment: .leading) {
    Text("🍛 curry and rice")
    Text("🥗 green salad")
  }
}
.padding()
.frame(width: 300)
.background(
  .background.secondary,
  in: .rect(cornerRadius: 8)
)

かなりコード量に差が出ますね。

 

🧑🏻‍💻 まとめ

便利ですね。

厳しいレイアウトの制限がない限り、

使う機会は多いかもしれません。

ちなみに、macOS で見てみると、

手書きのほうが意図通りとなりました。

少し残念。

👉 【SwiftUI】Default background Color in built-in View Component hatena-bookmark
👉 【SwiftUI】市松模様を背景にする - Checkered Pattern Background 🏁 hatena-bookmark
👉 【SwiftUI】四角の角を丸くする方法あれこれ hatena-bookmark
👉 【SwiftUI】 iOS / macOS の レイアウト記述を typealias で切り替える hatena-bookmark