はじめに
前回はLazyGridを使って、Cardの並びを自由に調整できるようにしました。
けれども、アニメーションはかなり不自然なので、位置関係をうまく調整すればなおせます。
目次
zIndex
・ListのアニメーションはCardと比べれば、若干硬くて、
タップジェスチャーが終わるタイミングで別のmatchedGeometryEffect
を呼び出します。
・また、matchedGeometryEffect
を区別するために、idの識別を変えます。
CoursesView.swift
//Card
VStack {
CourseItem(course: item)
.matchedGeometryEffect(
id: item.id, in: namespace, isSource: !show
)
.frame(width: 200, height: 200)
.onTapGesture {
withAnimation(.spring()) {
show.toggle()
selectedItem = item
isDisabled = true
}
}
.disabled(isDisabled)
}
.matchedGeometryEffect(
id: "container\(item.id)", in: namespace, isSource: !show
)
・ListにもCardと同じ作業します。アニメーションを遅らせる必要がなくなったので、消します。
CoursesView.swift
//List
VStack {
ForEach(0 ..< 20) { item in
CourseRow()
}
}
.padding()
.background(Color("Background 1"))
.matchedGeometryEffect(
id: "container\(selectedItem!.id)", in: namespace
)
<!--
.transition(
.asymmetric(
insertion: AnyTransition.opacity.animation(
Animation.spring().delay(0.3)
),
removal: AnyTransition.opacity.animation(.spring())
)
)
-->
.edgesIgnoringSafeArea(.all)
}
前後 ↓
・アニメーションをある程度整えたけど、ListはまだCardの裏側にあるので、zIndex
を使えば簡単にできます。
・裏にあるViewをzIndex(1)
で、表にあるViewをzIndex(2)
。
CoursesView.swift
//Card
{
//省略
.........
}
.zIndex(1)
//List
{
//省略
.........
}
.zIndex(2)
・今まではCardをタップして閉じるけど、わかりやすくするために閉じるボタンを入れるもありです。 ・新たに`CloseButton.swift`クラスを作ります。
CloseButton.swift
struct CloseButton: View {
var body: some View {
Image(systemName: "xmark")
.font(.system(size: 17, weight: .bold))
.foregroundColor(.white)
.padding(.all, 10)
.background(Color.black.opacity(0.6))
}
}
・CloseButtonをCardに置きます。onTapGesture
をCloseButtonに移動します。
CoursesView.swift
//List
CloseButton()
.padding(.trailing, 16)
.onTapGesture {
withAnimation(
.spring()) {
show.toggle()
selectedItem = nil
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5){
isDisabled = false
}
}
}
}
.zIndex(2)
まとめ
ソースコードGithub