xcode 如何修复SwiftUI tvOS ScrollView跳跃/抖动/片状/错误/故障行为?

wfveoks0  于 2022-11-26  发布在  Swift
关注(0)|答案(1)|浏览(151)

请看tvOS(版本14.7 18 M60)上滚动这个简单示例:

struct TestView: View
{
    var body: some View {
            ScrollView (.vertical, showsIndicators: false, content: {
                ForEach(0..<600) { index in
                    Button(action: {}, label: {Text("Button - \(index)")})
                        .background(Color.blue)
                        .padding()
                }
            })
    }
}

这个例子在连续滚动时会表现得很糟糕,滚动会停止移动,等待我在遥控器上完成滚动,在我在Apple TV遥控器上完成滑动后只有半秒钟,它就会更新视图并滚动到请求的位置,
See a video with this behavior
显然,这是一个不希望的行为,因为在滑动过程中,我看不到我已经到达了哪里,因此我必须停止滑动,允许视图刷新,只有在我看到滚动已经到达了哪里之后,我才可以决定是继续滚动还是向上滚动(如果需要)
它看起来像一个SwiftUI(尝试)优化性能,但它破坏了整个亚视应用程序的体验
我尝试使用ScrollViewReader修复它,如下所示:

import Foundation
import SwiftUI

struct FocusableButton: View
{
    @State var isFocused = false
    let index: Int
    var scrollView: ScrollViewProxy
    
    var body: some View
    {
        VStack
        {
            Text("Button - \(index)")
        }
            .id(index)
            .frame(width: 200, height: 100)
            .padding()
            .scaleEffect(isFocused ?  1.1 : 1)
            .background(isFocused ?  Color.white : Color.blue)
            .focusable(true, onFocusChange: { focused in
                isFocused = focused
                (focused ? {
                    scrollView.scrollTo(index)
                }() : { /* Lost Focus */ }())
            })
    }
}

struct TestView: View
{
    var body: some View {
        ScrollViewReader { scrollView in
            ScrollView (.vertical, showsIndicators: false, content: {
                ForEach(0..<600) { index in
                    FocusableButton(index: index, scrollView: scrollView)
                }
            })
        }
    }
}

see a video of how it behaves after the fix
但如果滚动太快-自动分页滚动启动并使应用程序崩溃,我会得到错误(在Xcode中):

Fatal error: ScrollViewProxy may not be accessed during view updates

和运行时问题:

Modifying state during view update, this will cause undefined behavior.

有没有人能帮忙?有没有办法解决它?(滚动问题或错误)
即使有一种方法可以绕过自动分页滚动,我也希望看到一个代码示例

shstlldc

shstlldc1#

奇怪的事实:如果你用一个List包围ScrollView(即使是1个虚拟项)-滚动行为正确

所以我用List实现了这个测试,它表现正确

struct TestView: View
{
    var body: some View {
        VStack(spacing: 40)
        {
            List(0..<600) { index in
                FocusableButton(index: index)
            }
        }
    }
}

所以我目前的结论是:

  • 快速用户界面
  • tvOS 14.7
  • 滚动视图
  • 针对每个
  • 可聚焦
    行不通!

如果我删除focusable并将其替换为button,则ScrollViewForEach也可以正常工作:

struct TestView: View
{
    var body: some View {
        VStack(spacing: 40)
        {
            List(0..<600) { index in
                Button(action: {}, label: {
                    Text("Button - \(index)")
                        .frame(width: 200, height: 100)
                        .padding()
                        .background(Color.blue)
                })
            }
        }
    }
}

但这三个组合(ScrollView + ForEach + focusable)的表现很差

相关问题