本文介绍了在复杂UI中使用SwiftUI的MatchedGeometryEffect的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
在我的应用程序中,我想在卡片和全屏覆盖之间创建一个‘英雄’动画,matchedGeometryEffect
似乎很适合。然而,无论我尝试什么,我都无法让动画像预期的那样工作,而且它看起来一点也不像通常的matchedGeometryEffect
动画。Here's它目前看起来是什么样子。这就是我目前所拥有的:(抱歉,代码太多了,但这是必要的,因为对于简单的视图来说,它工作得很好)
Something.swft
struct Something: Identifiable {
let id = UUID()
let image: Image
}
ContentView.swft
struct ContentView: View {
@Namespace var namespace
let items: [Something] = [
Image("a"), Image("b")
].map { Something(image: $0 )}
@State var selectedItem: Something?
var body: some View {
ZStack {
VStack {
ScrollView {
VStack(alignment: .leading) {
ForEach(items) { item in
CardView(
image: item.image,
namespace: namespace,
isSource: self.selectedItem == nil,
id: item.id
)
.background(Color.white)
.contentShape(RoundedRectangle(cornerRadius: 16, style: .continuous))
.zIndex(1)
.onTapGesture {
withAnimation(.spring()) {
self.selectedItem = item
}
}
}
}
}
}
.overlay(EmptyView())
if let item = selectedItem {
EventView(
image: item.image
) {
self.selectedItem = nil
}
.matchedGeometryEffect(id: item.id, in: namespace, isSource: false)
.zIndex(2)
}
}
.animation(.spring())
.transition(.scale)
}
}
CardView.wift
struct CardView: View {
let image: Image
let namespace: Namespace.ID
let isSource: Bool
let id: UUID
var body: some View {
VStack(alignment: .leading) {
ZStack(alignment: .bottomTrailing) {
image
.resizable()
.aspectRatio(contentMode: .fill)
.frame(height: 225)
.clipShape(RoundedRectangle(cornerRadius: 12, style: .continuous))
.matchedGeometryEffect(id: id, in: namespace, isSource: isSource)
}
}
}
}
EventView.swft
struct EventView: View {
let image: Image
let onDismiss: () -> Void
var body: some View {
image
.resizable()
.aspectRatio(contentMode: .fill)
.edgesIgnoringSafeArea(.all)
.onTapGesture(perform: onDismiss)
}
}
如有任何关于如何添加或更改以使其正常工作的建议,我们将不胜感激,谢谢!
推荐答案
我针对相同的需求所做的是将properties: .position
添加到matchedGeometryEffect
。然后,您需要指定如何从一个视图(比方说,缩略图卡片视图)转换到另一个(比方说,全屏卡片视图)。这是通过自定义转换实现的,如下所示:
extension AnyTransition
{
// This transition will pass a value (0.0 - 1.0), indicating how much of the
// transition has passed. To communicate with the view, it will
// use the custom environment key .modalTransitionPercent
// it will also make sure the transitioning view is not faded in or out and it
// stays visible at all times.
static var modal: AnyTransition
{
AnyTransition.modifier(active: ThumbnailExpandedModifier(pct: 0), identity: ThumbnailExpandedModifier(pct: 1))
}
struct ThumbnailExpandedModifier: AnimatableModifier
{
var pct: CGFloat
var animatableData: CGFloat
{
get { pct }
set { pct = newValue }
}
func body(content: Content) -> some View
{
return content
.environment(.modalTransitionPercent, pct)
.opacity(1)
}
}
}
extension EnvironmentValues
{
var modalTransitionPercent: CGFloat
{
get { return self[ModalTransitionKey.self] }
set { self[ModalTransitionKey.self] = newValue }
}
}
public struct ModalTransitionKey: EnvironmentKey
{
public static let defaultValue: CGFloat = 0
}
这篇关于在复杂UI中使用SwiftUI的MatchedGeometryEffect的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!