SwiftUI - 隐藏 ScrollView 的指示器使其停止滚动
Posted
技术标签:
【中文标题】SwiftUI - 隐藏 ScrollView 的指示器使其停止滚动【英文标题】:SwiftUI - Hiding a ScrollView's indicators makes it stop scrolling 【发布时间】:2019-11-30 14:28:16 【问题描述】:我试图隐藏 ScrollView
的指示符,但当我尝试这样做时,ScrollView
不再滚动。如果这很重要,我正在使用 macOS。
ScrollView(showsIndicators: false)
// Everything is in here
【问题讨论】:
看起来只有 macOS 的缺陷。在 ios 和 macCatalyst 上它可以工作。 我遇到了同样的问题,并希望它能在 macOS 10.15.1 和 Xcode 11.2 中得到修复。由于内容不再滚动,我还看到它仍然在顶部具有弹跳效果(有时也是如此)。 我面临同样的问题。在 iOS 上运行良好,但无法在 macOS 和 macCatalyst 上运行。 @Asperi - 你说它正在使用 macCatalyst - 你能展示你的代码吗? @SoOverIt,见答案。 这在 Big Sur 中已修复,但在 10.15.7 中仍未修复 【参考方案1】:应@SoOverIt 的要求
演示:
没什么特别的,只是启动了一些其他的测试示例。 Xcode 11.2 / macOS 10.15
var body : some View
VStack
ScrollView([.vertical], showsIndicators: false)
Group
Text("AAA")
Text("BBB")
Text("CCC")
Text("DDD")
Text("EEE")
Group
Text("AAA")
Text("BBB")
Text("CCC")
Text("DDD")
Text("EEE")
Group
Text("AAA")
Text("BBB")
Text("CCC")
Text("DDD")
Text("EEE")
Group
Text("AAA")
Text("BBB")
Text("CCC")
Text("DDD")
Text("EEE")
.frame(height: 100)
.border(Color.blue)
.border(Color.red)
【讨论】:
这很奇怪!我将您的代码复制并粘贴到一个新的 macCatalyst 应用程序中 - 仍然出现滚动错误。我正在使用 Xcode 11.3.1 和 macOS 10.15.3。我有以前使用它的记忆 - 也许它在 11.3.1 上很无聊?请参阅下面的视频答案。【参考方案2】:我解决了这个问题。
extension View
func hideIndicators() -> some View
return PanelScrollView self
struct PanelScrollView<Content> : View where Content : View
let content: () -> Content
var body: some View
PanelScrollViewControllerRepresentable(content: self.content())
struct PanelScrollViewControllerRepresentable<Content>: NSViewControllerRepresentable where Content: View
func makeNSViewController(context: Context) -> PanelScrollViewHostingController<Content>
return PanelScrollViewHostingController(rootView: self.content)
func updateNSViewController(_ nsViewController: PanelScrollViewHostingController<Content>, context: Context)
typealias NSViewControllerType = PanelScrollViewHostingController<Content>
let content: Content
class PanelScrollViewHostingController<Content>: NSHostingController<Content> where Content : View
var scrollView: NSScrollView?
override func viewDidAppear()
self.scrollView = findNSScrollView(view: self.view)
self.scrollView?.scrollerStyle = .overlay
self.scrollView?.hasVerticalScroller = false
self.scrollView?.hasHorizontalScroller = false
super.viewDidAppear()
func findNSScrollView(view: NSView?) -> NSScrollView?
if view?.isKind(of: NSScrollView.self) ?? false
return (view as? NSScrollView)
for v in view?.subviews ?? []
if let vc = findNSScrollView(view: v)
return vc
return nil
预览:
struct MyScrollView_Previews: PreviewProvider
static var previews: some View
ScrollView
VStack
Text("hello")
Text("hello")
Text("hello")
Text("hello")
Text("hello")
.hideIndicators()
【讨论】:
希望他们能尽快修复它,但这暂时可行。我不会考虑这个,只是复制意大利面,谢谢! 好吧,这个修复也给我带来了@ObservedObject 重新渲染视图的问题……不知道该怎么做才能防止这种情况发生。 @neptunes 同样在这里...不再更新视图。不能用这个【参考方案3】:所以...我认为这是目前唯一的方法。
您基本上只是在您的ScrollView
指示器上放置一个View
,并使用与您的背景相同的backgroundColor
View
注意:这显然只适用于您的背景是静态且后缘没有内容的情况。
想法
struct ContentView: View
@Environment(\.colorScheme) var colorScheme: ColorScheme
let yourBackgroundColorLight: Color = .white
let yourBackgroundColorDark: Color = .black
var yourBackgroundColor: Color colorScheme == .light ? yourBackgroundColorLight : yourBackgroundColorDark
var body: some View
ScrollView
VStack
ForEach(0..<1000) i in
Text(String(i)).frame(width: 280).foregroundColor(.green)
.background(yourBackgroundColor) //<-- Same
.overlay(
HStack
Spacer()
Rectangle()
.frame(width: 10)
.foregroundColor(yourBackgroundColor) //<-- Same
)
精简版
你可以这样改进,我想你已经在资产中动态设置了你的颜色。
用法:
ScrollView
...
.hideIndicators(with: <#Your Color#>)
实施:
extension View
func hideIndicators(with color: Color) -> some View
return modifier(HideIndicators(color: color))
struct HideIndicators: ViewModifier
let color: Color
func body(content: Content) -> some View
content
.overlay(
HStack
Spacer()
Rectangle()
.frame(width: 10)
.foregroundColor(color)
)
【讨论】:
以上是关于SwiftUI - 隐藏 ScrollView 的指示器使其停止滚动的主要内容,如果未能解决你的问题,请参考以下文章
SwiftUI:为啥这个 ScrollView 的内容错位了?