#swift #swiftui
Вопрос:
Я пытаюсь сделать вид изображения с возможностью прокрутки с помощью SwiftUI. Проводя пальцем влево/вправо, изображение перемещается влево/вправо, и когда вы проводите достаточно долго, изображение соскальзывает и появляется следующее/предыдущее изображение: точно так же, как вкладки на главном экране. Нажатие влево/вправо заставляет предыдущее/следующее изображение заменить текущее изображение, но без анимации.
Это представление получает массив изображений, индекс и смещение изображения.
Какой-то другой вид обнаруживает жест свайпа и изменяет индекс. Проблема в том, что когда жест свайпа изменяет индекс и слайды изображения, индекс меняется сразу после запуска анимации, а не после завершения анимации.
Похоже, это var currentIndex = index
и есть причина этой ошибки, ошибка, как я могу ее исправить?
struct MyImagesView: View {
@Binding var index:Int
let imgArray:[URL]
@Binding var dragOffset:CGSize
@State var nextindex:Int = 1
@State var screenSize:CGRect = UIScreen.main.bounds
var body: some View {
var currentindex = index
let insertionAnimation: ()->AnyTransition = { nextindex > currentindex ? AnyTransition.move(edge: .leading) : AnyTransition.move(edge: .trailing) }
let removalAnimation: ()->AnyTransition = { nextindex < currentindex ? AnyTransition.move(edge: .trailing) : AnyTransition.move(edge: .leading) }
ZStack {`enter code here`
MyImageView(array: imgArray,index:currentindex-2).offset(x: -screenSize.width, y: 0)
MyImageView(array: imgArray,index:currentindex-1)
MyImageView(array: imgArray,index:currentindex).offset(x: screenSize.width, y: 0)
}
.offset(dragOffset)
.onAppear(perform: { nextindex = index })
.onChange(of: index, perform: { value in
if dragOffset.width != 0 amp;amp; value != currentindex {
nextindex = value
Timer.scheduledTimer(withTimeInterval: 0.5, repeats: false, block: { _ in dragOffset = .zero; currentindex = value })
dragOffset.width = nextindex>currentindex ? -screenSize.width : (nextindex < currentindex ? screenSize.width : 0)
}
})
.transition(.asymmetric(insertion: insertionAnimation(), removal: removalAnimation()))
.animation(.linear(duration: (dragOffset.width==0) ? 0 : 0.5))
}
}
Ответ №1:
Я использовал таймер для изменения индекса после продолжительности анимации(=0,5 с), и это решило проблему. И не было никакой необходимости в переходе.
struct MyImagesView: View {
@Binding var index:Int
let imgArray:[URL]
@Binding var dragOffset:CGSize
@State var nextindex:Int = 1
@State var screenSize:CGRect = UIScreen.main.bounds
var body: some View {
ZStack {
MyImageView(array: imgArray, index: index-2).offset(x: -screenSize.width, y: 0)
MyImageView(array: imgArray, index: index-1)
MyImageView(array: imgArray, index: index).offset(x: screenSize.width, y: 0)
}
.offset(dragOffset)
.onAppear(perform: { nextindex = index })
.onChange(of: index, perform: { value in
if dragOffset.width != 0 {
dragOffset = .zero
}
})
.animation(.linear(duration: (dragOffset.width==0) ? 0 : 0.5))
}
}