我试图有一个字幕水平滚动的效果,但我的按钮是不可点击的。视图渲染良好,但当我点击按钮,它应该打印出'tapped user1',例如,但没有效果。
编辑:如果我按照建议在ScrollView上添加marquee修饰符,它会导致极其错误的滚动行为。理想情况下,这只是一个带有marquee的HStack,里面有一堆可点击的按钮,没有内置的滚动行为,但是如果没有ScrollView的 Package ,模块似乎就不能工作了。
我使用此链接创建了一个Marquee视图修改器:https://swiftuirecipes.com/blog/swiftui-marquee
我的视图代码如下:
struct MyView: View {
var body: some View {
let users = ["user1", "user2", "user3", "user4", "user5", "user6"]
return ScrollView(.horizontal, showsIndicators: false) {
HStack {
ForEach(users, id: \.self) { user in
if user == users.first {
Button(action: {
print("tapped \(user)")
}, label: {
Text(user)
})
} else {
Text("•")
Button(action: {
print("tapped \(user)")
}, label: {
Text(user)
})
}
}
}.frame(height: 20)
.marquee(duration: 10)
}
}
}
选取框教程中的代码如下所示:
struct Marquee: ViewModifier {
let duration: TimeInterval
let direction: Direction
let autoreverse: Bool
@State private var offset = CGFloat.zero
@State private var parentSize = CGSize.zero
@State private var contentSize = CGSize.zero
func body(content: Content) -> some View {
// measures parent view width
Color.clear
.frame(height: 0)
// measureSize from https://swiftuirecipes.com/blog/getting-size-of-a-view-in-swiftui
.measureSize { size in
parentSize = size
updateAnimation(sizeChanged: true)
}
content
.measureSize { size in
contentSize = size
updateAnimation(sizeChanged: true)
}
.offset(x: offset)
// animationObserver from https://swiftuirecipes.com/blog/swiftui-animation-observer
.animationObserver(for: offset, onComplete: {
updateAnimation(sizeChanged: false)
})
}
private func updateAnimation(sizeChanged: Bool) {
if sizeChanged || !autoreverse {
offset = max(parentSize.width, contentSize.width) * ((direction == .leftToRight) ? -1 : 1)
}
withAnimation(.linear(duration: duration)) {
offset = -offset
}
}
enum Direction {
case leftToRight, rightToLeft
}
}
extension View {
func marquee(duration: TimeInterval,
direction: Marquee.Direction = .rightToLeft,
autoreverse: Bool = false) -> some View {
self.modifier(Marquee(duration: duration,
direction: direction,
autoreverse: autoreverse))
}
}
struct SizePreferenceKey: PreferenceKey {
static var defaultValue: CGSize = .zero
static func reduce(value: inout CGSize, nextValue: () -> CGSize) {
value = nextValue()
}
}
struct MeasureSizeModifier: ViewModifier {
func body(content: Content) -> some View {
content.background(GeometryReader { geometry in
Color.clear.preference(key: SizePreferenceKey.self,
value: geometry.size)
})
}
}
extension View {
func measureSize(perform action: @escaping (CGSize) -> Void) -> some View {
self.modifier(MeasureSizeModifier())
.onPreferenceChange(SizePreferenceKey.self, perform: action)
}
}
public struct AnimationObserverModifier<Value: VectorArithmetic>: AnimatableModifier {
// this is the view property that drives the animation - offset, opacity, etc.
private let observedValue: Value
private let onChange: ((Value) -> Void)?
private let onComplete: (() -> Void)?
// SwiftUI implicity sets this value as the animation progresses
public var animatableData: Value {
didSet {
notifyProgress()
}
}
public init(for observedValue: Value,
onChange: ((Value) -> Void)?,
onComplete: (() -> Void)?) {
self.observedValue = observedValue
self.onChange = onChange
self.onComplete = onComplete
animatableData = observedValue
}
public func body(content: Content) -> some View {
content
}
private func notifyProgress() {
DispatchQueue.main.async {
onChange?(animatableData)
if animatableData == observedValue {
onComplete?()
}
}
}
}
public extension View {
func animationObserver<Value: VectorArithmetic>(for value: Value,
onChange: ((Value) -> Void)? = nil,
onComplete: (() -> Void)? = nil) -> some View {
self.modifier(AnimationObserverModifier(for: value,
onChange: onChange,
onComplete: onComplete))
}
}
2条答案
按热度按时间xn1cxnb41#
把修改器放在scrollview上,它会解决你的问题
就像这样。
gpnt7bae2#
尝试在按钮
.buttonStyle(PlainButtonStyle())
或其他类似按钮样式上添加修饰符。如果不起作用,则尝试只使用您想要的按钮标签并添加修饰符.onTapGesture {your code}