在移动视图内部时出现奇怪的滚动视图行为。斯威夫特用户界面
Weird ScrollView behaviour when its inside of moving View. SwiftUI
我有容器视图,可以四处拖动,里面有滚动视图和一堆按钮。当我拖动容器视图时,scrollViews 开始奇怪地上下跳跃,按钮的 hitboxes 也开始远离实际按钮。 (你可以看到我的gif)
但是当我触摸滚动视图时,一切都会恢复正常。
此代码仅供测试
这是主视图
struct ContentView: View {
@State var width : CGFloat = 300
@State var height : CGFloat = 300
var body: some View {
VStack{
SecondView(width: width, height: height){
ScrollView{
VStack{
ForEach(0...10, id : \.self){ i in
TestButton(number: i)
}
}
}
}
Slider(value: $width, in: 100...500)
Slider(value: $height, in: 100...500)
}
}
}
这就是可拖动视图
struct SecondView<Content : View> : View {
var width : CGFloat
var height : CGFloat
var content : () -> Content
@GestureState private var dragState = DragState.inactive
@State var position : CGSize = CGSize(width: 0, height: 0)
var body : some View {
let dragGesture = DragGesture().updating($dragState){ drag, state, transition in
state = .dragging(translation: drag.translation)
}.onEnded({drag in
self.position.height+=drag.translation.height
self.position.width+=drag.translation.width
})
return VStack{
Handle()
content().padding()
}.frame(width: width, height: height).background(Color.yellow).cornerRadius(10)
.offset(x: self.position.width + dragState.translation.width, y: self.position.height + dragState.translation.height)
.gesture(dragGesture)
}
enum DragState {
case inactive
case dragging(translation : CGSize)
var translation : CGSize {
switch self {
case .inactive:
return .zero
case .dragging(let translation):
return translation
}
}
var isDragging : Bool {
switch self {
case .inactive:
return false
case .dragging:
return true
}
}
}
}
我不确定这是一个错误还是我做错了什么,但看起来像错误
预先感谢您的回答和建议
.offset
修改器不会改变视图布局,所以移动的视图确实保持在同一个地方,点击区域保持在同一个地方,它只是绘制在不同的位置。
因此 .offset
不适合您的目标,而是重构为使用 .position
,这确实会改变视图层次结构(但也会影响整个布局,因此您的浮动窗格应放置在单独的位置ZStack
避开其他人)。
我有容器视图,可以四处拖动,里面有滚动视图和一堆按钮。当我拖动容器视图时,scrollViews 开始奇怪地上下跳跃,按钮的 hitboxes 也开始远离实际按钮。 (你可以看到我的gif)
但是当我触摸滚动视图时,一切都会恢复正常。
此代码仅供测试
这是主视图
struct ContentView: View {
@State var width : CGFloat = 300
@State var height : CGFloat = 300
var body: some View {
VStack{
SecondView(width: width, height: height){
ScrollView{
VStack{
ForEach(0...10, id : \.self){ i in
TestButton(number: i)
}
}
}
}
Slider(value: $width, in: 100...500)
Slider(value: $height, in: 100...500)
}
}
}
这就是可拖动视图
struct SecondView<Content : View> : View {
var width : CGFloat
var height : CGFloat
var content : () -> Content
@GestureState private var dragState = DragState.inactive
@State var position : CGSize = CGSize(width: 0, height: 0)
var body : some View {
let dragGesture = DragGesture().updating($dragState){ drag, state, transition in
state = .dragging(translation: drag.translation)
}.onEnded({drag in
self.position.height+=drag.translation.height
self.position.width+=drag.translation.width
})
return VStack{
Handle()
content().padding()
}.frame(width: width, height: height).background(Color.yellow).cornerRadius(10)
.offset(x: self.position.width + dragState.translation.width, y: self.position.height + dragState.translation.height)
.gesture(dragGesture)
}
enum DragState {
case inactive
case dragging(translation : CGSize)
var translation : CGSize {
switch self {
case .inactive:
return .zero
case .dragging(let translation):
return translation
}
}
var isDragging : Bool {
switch self {
case .inactive:
return false
case .dragging:
return true
}
}
}
}
我不确定这是一个错误还是我做错了什么,但看起来像错误 预先感谢您的回答和建议
.offset
修改器不会改变视图布局,所以移动的视图确实保持在同一个地方,点击区域保持在同一个地方,它只是绘制在不同的位置。
因此 .offset
不适合您的目标,而是重构为使用 .position
,这确实会改变视图层次结构(但也会影响整个布局,因此您的浮动窗格应放置在单独的位置ZStack
避开其他人)。