【SwiftUI】 Hero 애니메이션 시도

10815 단어 iOSSwiftSwiftUI

1. 소개



요 전날 Hero 애니메이션이라는 UI를 처음 알았습니다.

Hero 애니메이션은 화면 전환시 콘텐츠 비율을 변경하면서 전환합니다.
원활하게 움직인 것처럼 보이는 애니메이션입니다.

구체적으로는 iPhone의 사진도 그렇네요.
사진을 선택하면 확대되고 전체 화면에 표시되는 사람입니다.

이번에는 그런 최근 당연한 Hero 애니메이션
SwiftUI의 기본 라이브러리를 사용하여 구현하고 싶습니다.

2. 이미지



이번 기사의 내용을 사용하면 아래와 같은 UI를 만들 수 있게 됩니다.



3. 구현



그럼 구현해 봅시다.

이번에는 matchedGeometryEffect라는 수정자를 사용합니다.

3.1. 우선은 베이스를 만든다



베이스가 되는 화면을 만들어 갑니다.
struct ContentsView: View {
    @State var show = false

    var body: some View {
        VStack {
            if !self.show {
                Image("iPhone-5c-mockup-blue")
                    .resizable()
                    .aspectRatio(contentMode: .fit)
                    .frame(maxWidth: 200, maxHeight: 200)
            } else {
                Image("iPhone-5c-mockup-blue")
                    .resizable()
                    .aspectRatio(contentMode: .fit)
                    .background(Color(red: 66/255, green: 178/255, blue: 236/255))
                    .frame(maxWidth: .infinity, maxHeight: .infinity)
            }
        }
        .onTapGesture {
            self.show.toggle()
        }
    }
}

Image를 1개 표시할 뿐의 View가 되어 있어,
상태 변수 show의 상태에 따라 Image의 크기, 배경색을 바꾸고 있습니다.

그렇게 하면 아래와 같은 탭하면 사진이 화면 가득 펼쳐집니다.



이 상태에서는 화상의 전환이 일순간에 행해지므로 눈이 치카치카 해 버립니다.

3.2.Hero 애니메이션 적용



드디어 Hero 애니메이션을 적용하겠습니다.
방금 전 코드에 약간의 손을 추가합니다.

ContentView.swift

struct ContentView: View {
    // 画像がタップされているかどうかを保持する状態変数
    @State var show = false
    @Namespace var namespace

    var body: some View {
        VStack {
            if !self.show {
                // タップされていない時に表示する画像
                Image("iPhone-5c-mockup-blue")
                    .resizable()
                    .aspectRatio(contentMode: .fit)
                    .frame(maxWidth: 200, maxHeight: 200)
                    .matchedGeometryEffect(id: "zoom", in: namespace)

            } else {
                // タップされた時に表示する画像(高さと横幅をinfinityにしている)
                Image("iPhone-5c-mockup-blue")
                    .resizable()
                    .aspectRatio(contentMode: .fit)
                    .background(Color(red: 66/255, green: 178/255, blue: 236/255))
                    .frame(maxWidth: .infinity, maxHeight: .infinity)
                    .matchedGeometryEffect(id: "zoom", in: namespace)
            }
        }
        .onTapGesture {
            withAnimation(.default) {
                self.show.toggle()
            }

        }
    }
}

애니메이션을 만들려는 View에 matcheGeometryEffect 설정



네임스페이스와 ID를 전달하여 애니메이션을 만들 뷰를 그룹화합니다.
id는 그룹화하려는 View에서 동일하면 OK입니다.
.matchedGeometryEffect(id: "zoom", in: namespace)

애니메이션 설정



상태 변수 show의 갱신을 withAnimation의 클로저에 건네줍니다.
이렇게 하면 show 변수 업데이트와 관련된 View를 다시 그리는 데 애니메이션이 부여됩니다.
withAnimation(.default) {
       self.show.toggle()
}

그리고 할 수있는 것이 여기입니다.
애니메이션이 부여되었습니다!



4. 끝에



어땠습니까?
생각했던 것보다 쉽게 ​​구현할 수 있었습니다.

그리고는 배율을 바꾸거나 다른 View와 조합하는 것으로 최초로 보신 것 같은 UI도 만들 수 있습니다.

모두 꼭 사용해보십시오!

좋은 웹페이지 즐겨찾기