【SwiftUI】withAnimation() ↔ .animation()

特に、ざっくり

「あればいいかな」

くらいにアニメーションつけてました。


@State var animate1 = false

Text("😬")
  .font(.system(size: 200))
  .scaleEffect(animate1 ? 0.5 : 1.5)
  .rotationEffect(.degrees(animate1 ? 0 : 360))

  .onAppear {
    withAnimation(.default.repeatForever()) {
      animate1.toggle()
    }
  }

👉 withAnimation(_:_:) | Apple Developer Documentation hatena-bookmark

一方で、よく見かける似たような記述。


@State var animate2 = false

Text("😬")
  .font(.system(size: 200))
  .scaleEffect(animate2 ? 0.5 : 1.5)
  .rotationEffect(.degrees(animate2 ? 0 : 360))

  .animation(
    .default.repeatForever(),
    value: animate2
  )
  .onAppear {
    animate2.toggle()
  }

👉 animation(_:value:) | Apple Developer Documentation hatena-bookmark

どう違うのか並べてみましたが。

一緒ですね。

後者のほうが細かく使えそうな気がしますが、

前者のほうが簡潔です。

 

😃 参考

👉 【SwiftUI】アニメーションの書き方 hatena-bookmark


【SwiftUI】#Preview with @Binding arguments

#Preview@Binding の引数を持つ View をどう書くか。

サンプルとして以前のコードを使います。


.constant() を使うか、@State + return を使うか。


#Preview(".constant(\"\")") {
  TestSearchTextField(text: .constant(""))
    .frame(width: 300)
}

#Preview(".constant(\"dog\")") {
  TestSearchTextField(text: .constant("dog"))
    .frame(width: 300)
}

#Preview("return") {
  @State var text = "dog"
  return TestSearchTextField(text: $text)
    .frame(width: 300)
}

View パーツの確認をすばやく #Preview で確認できるようになりました !


【SwiftUI】色を付ける記述、ややこしすぎませんか?

目指すのはこれ。

緑色の四角の中に、

青色の文字と

オレンジ色の白文字ボタンを置くだけ。

どう書いてますか、色付けの記述。


.foregroundColor()
.foregroundStyle()
.foreground()
.backgroundStyle()
.background() 
.tint() 
// ...

意外と整理できてない私。

 

🤔 四角

VStack を使うとして。


VStack {
}
.frame(width: 100, height: 200)
//.backgroundStyle(.green) // no effect
.background(.green)

シンプルな単色であれば .background()

 

🤔 文字


Text("Hello")
  //.foregroundColor(.blue) // deprecated
  .foregroundStyle(.blue)
  //.tint(.blue) // no effect

将来 deprecated となるのは避けます。

.foreground() は使えないし suggestion にも表示されない。

公式サンプルをみても、

Text の色付けはすべて .foregroundStyle() となっていました。

 

🤔 ボタン

意外と悩みます。

文字とボタン表面の色、

押したり離したりしたときの色の変化、

角の形、

と要素が多いです。

それぞれに使えそうな modifier も複数あります。

多く試して、使いやすものを定型として覚えておきたいです。

まずは、角が丸いボタンなので .buttonStyle(.bordered) を使います。


Button("World") {
}
//.foregroundColor(.white) // deprecated
.foregroundStyle(.white)
//.backgroundStyle(.orange) // no effect
.buttonStyle(.bordered)
//.background(.orange) // break border
//.backgroundStyle(.orange) // no effect
//.tint(.orange) // only border

色と形とエフェクトを同時に満たすことができませんでした。

.tint() でいけそうに思えましたが、

きっちりとしたオレンジが表面に付きません。

次は .buttonStyle(.borderedProminent) を使います。

「prominent」の意味は、

prominent 形
1.〔周囲より〕高くなった、突き出した
2. 人目を引く、目立つ、派手な
3. 有名な、著名な、優れた、卓越した

なので、「目立つ突き出たボタン」ということですね。


Button("World") {
}
.buttonStyle(.borderedProminent)
//.foregroundStyle(.white) // no need default color
//.background(.orange) // wrong background
//.backgroundStyle(.orange) // no effect
.tint(.orange)

これですね !

ボタンを押したときの変化もいいかんじです。

label や makebody などを使おうとも思いましたが、

不必要に長くなりそうなのでやめておきました。

 

🤔 まとめ

最終的にこう書けました。


VStack {
  Text("Hello")
    .foregroundStyle(.blue)
  Button("World") {
  }
  .buttonStyle(.borderedProminent)
  .tint(.orange)
}
.frame(width: 100, height: 100)
.background(.green)

色付けのざっくりシンプルイメージとして、


// テキストやシンボル
.foregroundStyle()

// ボタン表面
.buttonStyle(.borderedProminent)
.tint()

// 固定の背景色
.background()

ぐらいから書き始めるのが良さげに思います。

それで意図通りにいかないときはさらに考えるかんじで。

すべてを覚えられないので簡単なものから順番に。