iyOmSd/Title: SwiftUI

[SwiftUI] Animation과 Transition

냄수 2022. 8. 19. 22:11
반응형

어느땐 애니메이션이 동작하고

어느땐 동작하지않는 그런 현상들이 많아서 정리하려고해요

 

 

우선 애니메이션을 줄 수 있는 방법으론 2가지가 있어요

withAnimation - 명시적인 애니메이션

animation - 암시적인 애니메이션

 

withAnimation

안에 넣은 코드를 통해 변경사항이 있는 뷰에 변화를 일으켜요

즉, 애니메이션을 발생시키는 곳이죠

transition을 사용할 수 있어요

주의할 점으론

withAnimation안에 animation을 사용해서는 안돼요

 

animation

뷰의 속성중 하나가 변경되면 자동으로 그 속성이 변경될때마다 애니메이션을 적용해요

주의할 점으론

컨테이너뷰에 애니메이션을 넣으면안된다는거에요

전체가 적용되는 현상이 있기때문에 최소단위로 실행하는것을 권장해요

 

그럼 transition은 뭐야??

직역으론 전환이죠

사라지고, 나타날때를 정의할때 사용해요

암시적 애니메이션(.animation)에서 동작하지 않아요

뷰가 오고 가는것, 즉 사라지고 나타는것 처럼 인식되지 않기때문에 전환에 사용할 수 없어요

명시적 애니메이션(withAnimation)과 함께사용해요

 

컨테이너뷰(ZStack같은 뷰를담는뷰)에 .animation을 사용하면 하위뷰 각각에 애니메이션을 제공해요

하지만 transition은 컨테이너뷰에 효과를 주면 컨테이너뷰에서 직접 일어나요

별개로 Group, ForEach와 같이 식별가능한 컨테이너뷰는 하위뷰 각각에 대해서 일어나요

 

전환효과를 주기위해서

ZStack을 사용한경우 ZStack전체가 사라지거나 나타나야 동작합니다

무슨말인지 잘 모르겠으니까 직접구현해서 비교해볼게요

 

테스트를위해서 VStack과 Group을 사용했어요

struct ContentView: View {
    @State private var isVStackHidden: Bool = false
    
    var body: some View {
        TestVStack(isHidden: $isVStackHidden).transition(.scale)
        Button("변경") {
            withAnimation {
                isVStackHidden.toggle()
            }
        }
    }
}

// Group
struct TestVStack: View {
    @Binding var isHidden: Bool
    
    var body: some View {
        Group {           << 변경
            Color.orange
            if isHidden {
            Text("Group입니다")
            }
        }
        .frame(width: 200, height: 200)
    }
}

// VStack
struct TestVStack: View {
    @Binding var isHidden: Bool
    
    var body: some View {
        VStack {           << 변경
            Color.orange
            if isHidden {
            Text("VStack입니다")
            }
        }
        .frame(width: 200, height: 200)
    }
}

transition으로 scale을 사용했어요

뷰가 사라지거나 나타날때 커지거나, 작아지는 동작을 기대할 수 있겠죠??

 

Group으로한경우

식별가능한 뷰이기때문에

하위뷰에 각각 scale이 적용되서

하위뷰중 하나가 사라진다면 scale transition으로 작아지는걸 볼수잇어요

또한, frame도 하위뷰 각각에 적용되서 Text의 크기도 커진걸 알 수 있죠

 

하지만

VStack인경우

scale transition동작을 하지않고

VStack의 기본동작인 fade in / fade out (opacity) transition으로 동작해요

왜냐하면 하위뷰가 아니라 VStack전체가 사라져야 scale transition이 동작하기 떄문이죠

 

이러한 특성을 잘 생각하면서 애니메이션을 적용해야해요

다른 컨테이너 뷰들과 다르게 List뷰는 기본전환으로 슬라이드 형식을 갖고있어요

List는 식별가능한 컨테이너 뷰에 속하므로

List에 전환효과를 적용한다면 잘 동작할거라고 생각하지만..!

각각의 Cell에는 적용되지않아요

Cell안에 있는 뷰에는 적용이 가능해도 

Cell이 나타나고 사라지는 transition은 불가능한거같아요
(혹시 알고계신다면 댓글남겨주세요 🐳)

 

ZStack같은 컨테이너뷰를 이용한 opacitiy효과, 아니면 기본 slide효과로 줄 수 있어요

Group과 같은 식별가능한 컨테이너뷰를 사용한다면 slide효과가 나타나요

struct TestList: View {
    enum ListType: String, CaseIterable {
        case a, b, c
    }
    @Binding var type: ListType
    
    var body: some View {
        List {
            // ZStack으로 감싸면 opacity효과가능
            sectionView()
        }
        .transition(.scale)
        .listStyle(.plain)
    }
    
    @ViewBuilder
    func sectionView() -> some View {
        switch type {
            case .a:
                Text("a타입")
                    .background(
                        Color.red
                    )
            case .b:
                Text("b타입")
                    .background(
                        Color.blue
                    )
            case .c:
                Text("c타입")
                    .background(
                        Color.yellow
                    )
        }
    }
}

 

 

 

 

 

반응형