在我尝试构建的应用程序中,我有一个带有圆圈的滚动视图。当用户点击一个圆圈时,它应该平滑地过渡到全屏矩形。
为了简单起见,我们将只专注于尝试从一个小圆圈过渡到一个全屏矩形。
第一步:检查Animatable
通过下面的代码,我们可以在一个圆和一个更大的矩形之间进行动画。证明RoundedRectangle()
视图和frame
视图修改器都是可动画的。
struct ContentView: View {
@State private var cornerRadius = 60.0
@State private var size = 100.0
var body: some View {
ZStack {
RoundedRectangle(cornerRadius: cornerRadius)
.foregroundStyle(.orange)
.frame(width: size, height: size)
}
.preferredColorScheme(.dark)
.animation(.linear, value: cornerRadius)
.animation(.linear, value: size)
.onTapGesture {
cornerRadius = cornerRadius == 0.0 ? 60.0 : 0.0
size = size == 100.0 ? 300.0 : 100.0
}
}
}
字符串
的数据
这就是我在视图之间转换时所追求的效果。
第二步:视图间切换
这里是事情变得复杂的地方。我们有两个不同的视图,紧凑版和全屏版。为了清楚起见,我把紧凑版做成了橙子,全屏版做成了红色,我是这样称呼它们的。
我们从前面的例子中删除了animatable属性,并将其替换为在true和false之间切换的isFullScreen属性。使用matchedGeometryEffect
,我们可以匹配大小和帧。据我所知,SwiftUI现在应该拥有所有构建块来在两个视图之间插入并平滑过渡。然而,事实并非如此。
struct ContentView: View {
@Namespace private var namespace
@State private var isFullScreen = false
var body: some View {
ZStack {
if !isFullScreen {
RoundedRectangle(cornerRadius: 60.0)
.foregroundStyle(.orange)
.matchedGeometryEffect(id: "item", in: namespace)
.frame(width: 100.0, height: 100.0)
} else {
RoundedRectangle(cornerRadius: 0.0)
.foregroundStyle(.red)
.matchedGeometryEffect(id: "item", in: namespace)
.frame(width: 300.0, height: 300.0)
}
}
.preferredColorScheme(.dark)
.animation(.linear, value: isFullScreen)
.onTapGesture {
isFullScreen.toggle()
}
}
}
型
的
从渐变动画和重影来看,SwiftUI似乎不知道该怎么做。因此,当转换时,橙子视图将获得它提供的拐角半径,并且不会将此属性从原始的60.0动画到新的0.0。至于红色视图,它不会将此属性从60.0动画到0.0。它唯一做的就是动画大小。
我如何教SwiftUI相应地转换角半径?因此,两个视图都模仿彼此的行为,它将显示为一个视图。
4条答案
按热度按时间yrdbyhpb1#
你可以尝试这种方法,如示例代码所示。
字符串
6za6bjd02#
根据您的评论,如果您希望动画在两个单独的视图之间转换时发生,那么您最好的选择是使用角半径的状态变量。这并不完美,但比之前的好:
字符串
1.尽管我们设置动画为线性,但插入的视图会快速变大。两个视图都应该模仿这种行为,因此不会出现重影。
我怀疑这是因为
matchedGeometryEffect
正在缩放视图,所以从绝对意义上说半径大小不匹配。您可以通过放弃使用matchedGeometryEffect并使用一个用于大小的状态变量来解决这个问题(就像角半径的状态变量一样)。使用此状态变量来控制maxWidth和maxHeight。1.如果反转动画,插入的视图将不会对角设置动画。
如果你的意思是,切换if-else,那么确保cornerRadius初始化为正确的值。你还需要更改matchedGeometryEffect的标志
isSource
。1.如果您中断动画,并且它再次变大,则角将保持圆形。
是的,如果你在动画发生时双击,那么错误的半径可能会生效。这也可以通过添加onDisappear回调来解决。
另一种实现效果的方法是完全避免使用过渡。您可以使用不透明度来控制可见性,然后使用完全模仿彼此的动画。这允许平滑地更改角半径和大小。不确定它是否适用于现实世界。
型
im9ewurl3#
几天后,我终于想出了一个有效的解决方案。
字符串
的数据
qrjkbowd4#
字符串
的数据