我已经使用 SwiftUI 实现了示例视频编辑时间线,但遇到了问题。因此,我将问题分成几个部分,并将每个问题作为一个单独的问题发布。 在下面的代码中,我有一个简单的时间线,使用
HStack
,其中包含左间隔符、右间隔符(表示为简单的黑色)和中间的修剪器 UI。拖动左右手柄时,修剪器会调整大小。当拖动修剪器手柄时,左右垫片的宽度也会调整。
问题:我想在修剪器调整大小时保持修剪器中的背景缩略图(当前实现为填充不同颜色的简单矩形)静止。目前,它们随着修剪器调整大小而移动,如下图所示。我该如何解决它?
import SwiftUI
struct SampleTimeline: View {
let viewWidth:CGFloat = 340 //Width of HStack container for Timeline
@State var frameWidth:CGFloat = 280 //Width of trimmer
var minWidth: CGFloat {
2*chevronWidth + 10
} //min Width of trimmer
@State private var leftViewWidth:CGFloat = 20
@State private var rightViewWidth:CGFloat = 20
var chevronWidth:CGFloat {
return 24
}
var body: some View {
HStack(spacing:0) {
Color.black
.frame(width: leftViewWidth)
.frame(height: 70)
HStack(spacing: 0) {
Image(systemName: "chevron.compact.left")
.frame(width: chevronWidth, height: 70)
.background(Color.blue)
.gesture(
DragGesture(minimumDistance: 0)
.onChanged({ value in
leftViewWidth = max(leftViewWidth + value.translation.width, 0)
if leftViewWidth > viewWidth - minWidth - rightViewWidth {
leftViewWidth = viewWidth - minWidth - rightViewWidth
}
frameWidth = max(viewWidth - leftViewWidth - rightViewWidth, minWidth)
})
.onEnded { value in
}
)
Spacer()
Image(systemName: "chevron.compact.right")
.frame(width: chevronWidth, height: 70)
.background(Color.blue)
.gesture(
DragGesture(minimumDistance: 0)
.onChanged({ value in
rightViewWidth = max(rightViewWidth - value.translation.width, 0)
if rightViewWidth > viewWidth - minWidth - leftViewWidth {
rightViewWidth = viewWidth - minWidth - leftViewWidth
}
frameWidth = max(viewWidth - leftViewWidth - rightViewWidth, minWidth)
})
.onEnded { value in
}
)
}
.foregroundColor(.black)
.font(.title3.weight(.semibold))
.background {
HStack(spacing:0) {
Rectangle().fill(Color.red)
.frame(width: 70, height: 60)
Rectangle().fill(Color.cyan)
.frame(width: 70, height: 60)
Rectangle().fill(Color.orange)
.frame(width: 70, height: 60)
Rectangle().fill(Color.brown)
.frame(width: 70, height: 60)
Rectangle().fill(Color.purple)
.frame(width: 70, height: 60)
}
}
.frame(width: frameWidth)
.clipped()
Color.black
.frame(width: rightViewWidth)
.frame(height: 70)
}
.frame(width: viewWidth, alignment: .leading)
}
}
#Preview {
SampleTimeline()
}
目前,颜色显示在嵌套
HStack
的背景中。然而,这个HStack
正在移动,具体取决于leftViewWidth
的大小。因此,尽管您在背景上设置了较小的帧大小,但您并没有补偿堆栈的位置。
我建议使用不同的方法。不要尝试剪辑背景,只需保持其不变并应用
.mask
来控制应该可见的部分。
您之前接受了拖动修剪器的不同解决方案,该解决方案使用
GestureState
变量来跟踪拖动位置(这是我的答案)。问题中的示例以不同的方式进行。下面的版本基于我之前提供的相同解决方案。我建议,这是一种更简单的方法。
struct SampleTimeline: View {
let viewWidth: CGFloat = 340 //Width of HStack container for Timeline
let chevronWidth: CGFloat = 24
let minWidth: CGFloat = 10
@State private var leftOffset: CGFloat = 0
@State private var rightOffset: CGFloat = 0
@GestureState private var leftDragOffset: CGFloat = 0
@GestureState private var rightDragOffset: CGFloat = 0
private func leftAdjustment(dragOffset: CGFloat) -> CGFloat {
let maxAdjustment = viewWidth - rightOffset - (2 * chevronWidth) - minWidth
return max(0, min(leftOffset + dragOffset, maxAdjustment))
}
private func rightAdjustment(dragOffset: CGFloat) -> CGFloat {
let maxAdjustment = viewWidth - leftOffset - (2 * chevronWidth) - minWidth
return max(0, min(rightOffset - dragOffset, maxAdjustment))
}
// private var frameWidth: CGFloat {
// viewWidth
// - (2 * chevronWidth)
// - leftAdjustment(dragOffset: leftDragOffset)
// - rightAdjustment(dragOffset: rightDragOffset)
// }
var body: some View {
HStack(spacing: 0) {
Image(systemName: "chevron.compact.left")
.frame(width: chevronWidth, height: 70)
.background(Color.blue)
.offset(x: leftAdjustment(dragOffset: leftDragOffset))
.gesture(
DragGesture(minimumDistance: 0)
.updating($leftDragOffset) { value, state, trans in
state = value.translation.width
}
.onEnded { value in
leftOffset = leftAdjustment(dragOffset: value.translation.width)
}
)
Spacer()
Image(systemName: "chevron.compact.right")
.frame(width: chevronWidth, height: 70)
.background(Color.blue)
.offset(x: -rightAdjustment(dragOffset: rightDragOffset))
.gesture(
DragGesture(minimumDistance: 0)
.updating($rightDragOffset) { value, state, trans in
state = value.translation.width
}
.onEnded { value in
rightOffset = rightAdjustment(dragOffset: value.translation.width)
}
)
}
.foregroundColor(.black)
.font(.title3.weight(.semibold))
.background {
HStack(spacing: 0) {
Color.red
Color.cyan
Color.orange
Color.brown
Color.purple
}
.padding(.vertical, 5)
.padding(.horizontal, chevronWidth)
.background(.background)
.mask {
Rectangle()
.padding(.leading, leftAdjustment(dragOffset: leftDragOffset))
.padding(.trailing, rightAdjustment(dragOffset: rightDragOffset))
}
}
.frame(width: viewWidth)
.background(.black)
}
}