일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- Animation
- node
- junit
- MotionLayout
- PagingLib
- GCP
- rx
- MediaSession
- Reactive
- paging
- Kotlin
- list
- MediaPlayer
- google play
- 동영상
- Android 13
- android13
- 테스트 자동화
- SWIFTUI
- SwiftUI Tutorial
- Android
- RxKotlin
- databinding
- mysql
- Observable
- node.js
- Koin
- 인앱결제
- mvvm
- liveData
- Today
- Total
봄날은 갔다. 이제 그 정신으로 공부하자
5. SwiftUI Tutorial - animation 본문
이 글은 swiftUI Tutorial 중 5번째 항목인 "Animating views and Transitions" 내용을 기반으로 설명합니다.
전체 소스 및 내용이 궁금하신 분은 아래 링크를 참고해주세요.
https://developer.apple.com/tutorials/swiftui/animating-views-and-transitions
버튼에 Animation 효과 추가하기
아래 이미지 우측 화살표 버튼을 클릭하면
아래 이미지와 같이 1.5배 커지면서 화살표가 90도 돌아가는 애니메이션을 예를 들어 설명하도록 하겠습니다.
위 조건을 만족 시키기 위해 아래와 같이 버튼을 생성해 줍니다.
* 전체 소스는 위 링크를 참고해주세요.
@State private var showDetail = false
...
Button {
showDetail.toggle()
} label: {
Label("Graph", systemImage: "chevron.right.circle")
.labelStyle(.iconOnly)
.imageScale(.large)
.rotationEffect(.degrees(showDetail ? 90 : 0))
.scaleEffect(showDetail ? 1.5 : 1)
.padding()
.animation(.easeInOut, value: showDetail)
}
rotationEffect()
위 소스 중 버튼의 회전을 담당하는 부분은 rotationEffect() 함수이며 이 함수로 인해 사용자가 버튼을 클릭할 때마다 90도를 회전시켰다가 다시 원위치 시켰다를 반복합니다.
scaleEffect()
버튼의 크기를 조절하는 함수는 scaleEffect() 함수로 이 함수로 인해 사용자가 버튼을 클릭할 때마다 아이콘의 크기가 늘어났다 줄어들었다를 반복합니다. 위 두 개 함수만 사용한다면 사용자가 버튼을 눌렀을 때 그냥 이미지가 돌아가고 아이콘의 크기가 변하기만 하지 애니메이션 효과가 적용되지는 않습니다.
animation()
애니메이션 효과를 적용하기 위해서는 animation() 함수를 사용해야 합니다.
위 예시에서는 애니메이션 효과로 easeInOut를 사용하였습니다.
easeInOut 외에 지원하는 애니메이션 효과에 대해서는 아래 "Animation struct 정의"에서 자세히 설명합니다.
withAnimation()
애니메이션의 유지 시간을 개발자가 정할 수 있는데 이를 사용하기 위해서는 아래와 같이 withAnimation()함수를 사용해야 합니다.
Button {
withAnimation(.easeInOut(duration: 4)) {
showDetail.toggle()
}
} label: {
Label("Graph", systemImage: "chevron.right.circle")
.labelStyle(.iconOnly)
.imageScale(.large)
.rotationEffect(.degrees(showDetail ? 90 : 0))
.scaleEffect(showDetail ? 1.5 : 1)
.padding()
}
Animation struct 정의
SwiftUI에 정의된 Animation을 보면 아래와 같이 iOS는 버전 13.0부터 지원됨을 알 수 있으며
@available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *)
@frozen public struct Animation : Equatable {
/// Returns a Boolean value indicating whether two values are equal.
///
/// Equality is the inverse of inequality. For any values `a` and `b`,
/// `a == b` implies that `a != b` is `false`.
///
/// - Parameters:
/// - lhs: A value to compare.
/// - rhs: Another value to compare.
public static func == (lhs: Animation, rhs: Animation) -> Bool
}
또 아래와 같은 여러 애니메이션 효과를 기본적으로 지원함을 알 수 있으며,
@available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *)
extension Animation {
public static func easeInOut(duration: Double) -> Animation
public static var easeInOut: Animation { get }
public static func easeIn(duration: Double) -> Animation
public static var easeIn: Animation { get }
public static func easeOut(duration: Double) -> Animation
public static var easeOut: Animation { get }
public static func linear(duration: Double) -> Animation
public static var linear: Animation { get }
public static func timingCurve(_ c0x: Double, _ c0y: Double, _ c1x: Double, _ c1y: Double, duration: Double = 0.35) -> Animation
}
SwiftUI Animation은 delay와 speed를 조절하는 함수 및 반복 횟수를 지정하는 repeatCount()와 repeatForever() 함수 또한 지원하고 있습니다.
@available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *)
extension Animation {
public func delay(_ delay: Double) -> Animation
}
@available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *)
extension Animation {
/// Returns an animation that has its speed multiplied by `speed`. For
/// example, if you had `oneSecondAnimation.speed(0.25)`, it would be at 25%
/// of its normal speed, so you would have an animation that would last 4
/// seconds.
public func speed(_ speed: Double) -> Animation
}
@available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *)
extension Animation {
public func repeatCount(_ repeatCount: Int, autoreverses: Bool = true) -> Animation
public func repeatForever(autoreverses: Bool = true) -> Animation
}
Animation 좀 더 풍성하게 사용하기
SwiftUI Animation에서 많은 것을 지원해주어도 개발시에는 추가로 애니메이션 효과를 만들어야할 때가 있습니다.
스프링 효과를 2배속으로 주는 애니메이션을 만들어 보겠습니다.
만들어진 코드는 아래와 같습니다.
extension Animation {
static func ripple() -> Animation {
Animation.spring(dampingFraction: 0.5).speed(2)
}
}
// spring()함수에서 지원하는 파라미터 설명은 다음과 같습니다.
// - response: 스프링의 강성을 나타내는 값으로 0이면 무한히 단단해져 스프핑 효과 없음.
// - dampingFraction: 애니메이션되는 값에 적용된 드래그의 크기로 0에서 1사이의 값을 사용하며 0은 절대 멈추지 않음.
// - blendDuration: 스프링의 response에 대한 변경 사항을 보간할 기간(단위:sec)입니다.
// speed는 배속으로 기본값이 1이며, 2는 2초가 아닌 2배속 입니다.
AnyTransition 좀 더 풍성하게 사용하기
애니메이션처럼 Transition도 개발자가 View가 보여지는 방식을 지정할 수 도 있습니다.
아래 코드와 같이 transition()함수에 slide 트랜지션을 사용하면 View가 보여질때는 leading이 사라질때는 trailing이 적용되지만
HikeDetail(hike: hike).transition(.slide)
이런거 싫고 위에서 나타났다 위로 사라지는 것을 원할 때는 transition() 함수에 top을 직접적으로 사용할 수 없으므로 아래와 같이 작업을 해주어야 합니다.
HikeDetail(hike: hike).transition(.moveAndFade)
...
extension AnyTransition {
static var moveAndFade: AnyTransition {
AnyTransition.move(edge: .top)
}
}
나타날때와 사라질때는 구분해 처리하고자 할 때는 아래와 같이 asymmetric() 함수를 사용해 방향성을 지정할 수 있습니다.
extension AnyTransition {
static var moveAndFade: AnyTransition {
.asymmetric(
insertion: .move(edge: .leading).combined(with: .opacity),
removal: .scale.combined(with: .opacity)
)
}
}
정리
간단합니다. 아래 내용만 알면 됩니다.
1. rotationEffect()은 회전 효과 함수
2. scaleEffect()은 사이즈 효과 함수
3. animation()은 애니메이션 처리 함수로 위 두 개 함수와 같이 사용하면 조금 더 풍성한 애니메이션 효과를 연출할 수 있음.
4. 애니메이션의 유지 시간 등 다양한 효과를 추가하기 위해서는 withAnimation() 함수를 사용해야 함.
5. Animation은 아래와 같은 다양한 애니메이션 효과를 기본 지원함.
- easeInOut
- easeIn
- easeOut
- linear
- timingCurve
- 추가로 speed, delay, repeat 등을 지원함.
6. 필요하다면 extension을 사용해 Animation 뿐만 아니라 Transition 효과도 좀 더 풍성하게 사용할 수 있음.
'iOS Tip' 카테고리의 다른 글
배경이 투명한 ViewController 만들기 (0) | 2022.03.30 |
---|---|
이미지 라운드 처리하기 (0) | 2022.03.25 |
3-2. SwiftUI Tutorial - ObservableObject, @Published, @ObservedObject, @EnvironmentObject (0) | 2022.03.12 |
3-1. SwiftUI Tutorial - List filter & sort (0) | 2022.03.08 |
2-2. SwiftUI Tutorial - List (0) | 2022.03.04 |