我有一个View,在其中我使用Picture(图像)子视图显示图像,该图像可以具有不同的高度和宽度格式。
对图像的引用是从数组中提取的,这使我可以通过更改引用在视图中显示不同的图像。 SwiftUI重新排列每个新图像的视图内容
我想在显示图像时在此图像上显示动画,例如缩放效果
1)我需要第一个.animation(nil)来避免对前一个图像进行动画处理(否则,我会出现难看的淡出效果和长宽比变形)。似乎是很好的解决方法
2)但是,我的scaleEffect修饰符有一个问题(即使我将其设置为scale = 1,它也不应该执行任何操作)
动画通过强加图像2的左上角从图像1的左上角开始而从图像1移动到图像2,该宽度和高度不同,会引起图像中心的不必要平移
这在下面的代码中进行了复制,出于演示目的,我正在使用系统映像(不容易出现错误1)
如何避免这种情况?
3)在下面的演示代码中,我使用一个按钮触发了新图像,这使我可以使用动作并处理“缩放”修改,并明确实现所需的效果。但是在我的真实代码中,图像修改是由另一个视图中的另一个更改触发的。
Swift知道这一点,因此我可以使用隐式的.animation修饰符。
但是,我不知道如何对任何新图像施加“比例”重置并达到我想要的效果。
如果我使用onAppear(我的代码),则仅适用于显示的第一个图像,而不适用于随后的图像。
在真实代码中,我有一个Picture(图像)视图,而Picture(image.animation())无法编译。
有什么想法如何在隐式动画的Button中实现以下代码中的操作?
谢谢
import SwiftUI
let portrait = Image(systemName: "square.fill")
let landscape = Image(systemName: "square.fill")
struct ContentView: View {
@State var modified = false
@State var scale: CGFloat = 1
var body: some View {
return VStack(alignment: .center) {
Pictureclip(bool: $modified)
.animation(nil)
.scaleEffect(scale)
.animation(.easeInOut(duration: 1))
Button(action: {
self.modified.toggle()
self.scale = 1.1
DispatchQueue.main.asyncAfter(deadline: .now() + 1)
{self.scale = 1}
}) {
Text("Tap here")
.animation(.linear)
}
}
}
}
struct Pictureclip: View {
@Binding var bool: Bool
var body: some View {
if bool == true {
return portrait
.resizable()
.frame(width: 100, height: 150)
.foregroundColor(.green)
} else {
return landscape
.resizable()
.frame(width: 150, height: 100)
.foregroundColor(.red)
}
}
}
答案 0 :(得分:0)
我对问题有一个半答案,即第1点和第2点(此处参考资产目录中的两个jpeg图像)
import SwiftUI
let portrait = Image("head")
let landscape = Image("sea")
struct ContentView: View {
@State var modified = false
@State var scale: CGFloat = 0.95
var body: some View {
VStack(){
GeometryReader { geo in
VStack {
Picture(bool: self.modified)
.frame(width: geo.size.width * self.scale)
}
}
Spacer()
Button(action: {
self.scale = 0.95
self.modified.toggle()
withAnimation(.easeInOut(duration: 0.5)){
self.scale = 1
}
}) {
Text("Tap here")
}
}
}
}
struct Picture: View {
var bool: Bool
var body: some View {
if bool == true {
return portrait
.resizable().aspectRatio(contentMode: .fit)
.padding(.all,6.0)
} else {
return landscape
.resizable().aspectRatio(contentMode: .fit)
.padding(.all,6.0)
}
}
}
此解决方案可实现缩放,而不会在动画过程中扭曲新图像的纵横比。但是,它不适用于在另一个视图中触发图像更新的代码。我想我必须重组我的代码,以解决问题或更清楚地揭示它。
编辑:一种快速而肮脏的解决方案是将触发代码(此处为按钮中的操作代码)放在另一个视图中。即,将传递视图状态动画的代码(传递给它的状态变量)放入视图B中(此处为“缩放”)。我敢肯定有更清洁的方法,但是至少这是可行的。
答案 1 :(得分:0)
我不确定,但也许对你有帮助。 使用数据绑定结构。我是这样用的:
let binding = Binding<String>(get: {
self.storage
}, set: { newValue in
self.textOfPrimeNumber = ""
self.storage = newValue
let _ = primeFactorization(n: Int(self.storage)!, k: 2, changeable: &self.textOfPrimeNumber)
})