【SwiftUI】Default background Color in built-in View Component

上は GroupBox を使って、

下は それに似せて Stack系のViewで書く。


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

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

背景色が違う !

 

🧑🏻‍💻 意図しない背景色

特に背景色を意識せずに画面を構成していくと、

微妙に色が違うことありません ?

そもそもデフォルトの背景色はどんな色なのですか。

もちろん、Color クラスに定義されてますよね?

簡単に呼び出せますよね ?

Light / Dark の変化に対応してますよね ?

 

🧑🏻‍💻 地道に調べる

Xcode のカラーピッカーで調べます。


Edit

 ↓

Format

 ↓

Show Colors

RGB で opacity 100% で


//       light               dark  
// 0.949 0.949 0.969 | 0.110 0.110 0.118

でした。

 

🧑🏻‍💻 既存の背景色 (Light/Dark 対応)

これ、SwiftUI.Color で定義されてませんよね。

UIColor の定義でそれらしきのものを見つけて、

数値を取ってみます。


//                           opacity 100%          light               dark
Color(.systemBackground)                  // 1.000 1.000 1.000 | 0.000 0.000 0.000
Color(.secondarySystemBackground)         // 0.949 0.949 0.969 | 0.110 0.110 0.118
Color(.tertiarySystemBackground)          // 1.000 1.000 1.000 | 0.173 0.173 0.180
Color(.systemGroupedBackground)           // 0.949 0.949 0.969 | 0.000 0.000 0.000
Color(.secondarySystemGroupedBackground)  // 1.000 1.000 1.000 | 0.110 0.110 0.118
Color(.tertiarySystemGroupedBackground)   // 0.949 0.949 0.969 | 0.173 0.173 0.180

どうやら、GroubBox デフォルト背景色は、


Color(.secondarySystemBackground)

と同じもののようです。

GroupBoxStyle に定義されているのでしょうが、

見つけられませんでした。

 

🧑🏻‍💻 まとめ

こういうの困りません?

なんだか単に「色」といってもかなり深そう。

👉 大解剖!UIColorファミリー by しもとり | トーク | iOSDC Japan 2020 - fortee.jp hatena-bookmark

iOS まわりの激しい変化の歴史を感じます。

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


【SwiftUI】View を ドラッグ して移動 する

View をドラッグして動かします。


struct TestDragGesture: View {
  @State private var location = CGPoint(x: 150, y: 150)

  var body: some View {
    ZStack {
      VStack(alignment: .trailing) {
        Text("location.x: \(location.x)")
        Text("location.y: \(location.y)")
      }
      .monospaced()

      Circle()
        .fill(.red.opacity(0.5))
        .frame(width: 100)
        .position(location)
        .gesture(
          DragGesture()
            .onChanged { value in
              location = value.location
            }
        )
    }
  }
}

ドラッグ位置が変化するたびに View の位置を更新できます。

var location: CGPoint
The location of the drag gesture’s current event.

👉 DragGesture.Value | Apple Developer Documentation hatena-bookmark

Circle の position は Viewの中心

であることに対して

DragGesture().onChanged() で取得したドラッグ位置

とずれがあるため、

タップ位置を動かした瞬間に中心位置にジャンプしてしまいます。

なんか違和感がありますね !

 

👩🏼‍💻 startLocation と translation

計算方法を変えます。

以下を使います。

var startLocation: CGPoint
The location of the drag gesture’s first event.

var translation: CGSize
The total translation from the start of the drag gesture to the current event of the drag gesture.

👉 DragGesture.Value | Apple Developer Documentation hatena-bookmark


Circle()
  .fill(.red.opacity(0.5))
  .frame(width: 100)
  .position(location)
  .gesture(
    DragGesture()
      .onChanged { value in
        var newLocation = startLocation ?? location
        newLocation.x += value.translation.width
        newLocation.y += value.translation.height
        location = newLocation
      }
      .updating($startLocation) { _, startLocation, _ in
        startLocation = startLocation ?? location
      }
   )

Circle の中心位置に対して、ドラッグの移動量を増減することで、なめらかに違和感なく動くようになりました !



簡単なコードに見えますが、updating を使った位置情報の入れ替えとか、よくみると深い。

👉 updating(_:body:) | Apple Developer Documentation hatena-bookmark
👉 Move your view around with Drag Gesture in SwiftUI | Sarunw hatena-bookmark

しかし、なんか見通しが悪い。

@GestureState と updating() は使いづらい。

 

👩🏼‍💻 まとめ

これでいきます。



キモは、

「ドラッグの移動量を View のポジションに適用」

「ドラッグ開始時のドラッグ位置とView中心のズレ」



【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