Skip to content

Instantly share code, notes, and snippets.

@Lavmint
Created March 31, 2021 12:32
Show Gist options
  • Save Lavmint/2e6f4f45d0cfbb6242c6f13e6926ec00 to your computer and use it in GitHub Desktop.
Save Lavmint/2e6f4f45d0cfbb6242c6f13e6926ec00 to your computer and use it in GitHub Desktop.
Marque horizontal view
import Foundation
import SwiftUI
extension View {
func marque() -> some View {
modifier(HorizontalMarqueModifier())
}
}
fileprivate struct HorizontalMarqueModifier: ViewModifier {
func body(content: Content) -> some View {
HorizontalMarqueView {
content
}
}
}
fileprivate struct HorizontalMarqueViewState {
var parentSize: CGSize?
var childSize: CGSize?
var isActive = false
var isFit: Bool {
guard let p = parentSize, let c = childSize else {
return true
}
return c.width < p.width
}
var xOffset: CGFloat {
guard let p = parentSize, let c = childSize else {
return 0
}
guard !isFit else {
return 0
}
return p.width - c.width
}
}
fileprivate struct HorizontalMarqueView<Content: View>: View {
@State var state = HorizontalMarqueViewState()
let content: () -> Content
var body: some View {
GeometryReader { parent in
ScrollView(.horizontal, showsIndicators: false) {
content()
.disabled(false)
.background(
GeometryReader { (child) in
Path()
.onAppear {
state.childSize = child.size
}
}
)
.offset(x: state.isActive ? state.xOffset : 0)
.animation(state.isFit ? nil : Animation.linear(duration: 1.5).repeatForever(autoreverses: false))
.onAppear {
state.parentSize = parent.size
}
}
.disabled(true)
}
.onChange(of: state.childSize) { (cz) in
state.isActive = !state.isFit
}
.onChange(of: state.parentSize) { (pz) in
state.isActive = !state.isFit
}
.frame(width: state.parentSize?.width, height: state.childSize?.height)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment