我一直在使用 ScrollView 看到首选项键的一些奇怪行为。如果我把它放在onPreferenceChange里面ScrollView它不会被调用,但如果我把它放在外面它会!
我已经设置了一个宽度首选项键,如下所示:
struct WidthPreferenceKey: PreferenceKey {
typealias Value = CGFloat
static var defaultValue = CGFloat(0)
static func reduce(value: inout CGFloat, nextValue: () -> CGFloat) {
value = nextValue()
}
}
Run Code Online (Sandbox Code Playgroud)
以下简单视图不会打印:
struct ContentView: View {
var body: some View {
ScrollView {
Text("Hello")
.preference(key: WidthPreferenceKey.self, value: 20)
.onPreferenceChange(WidthPreferenceKey.self) {
print($0) // Not being called, we're in a scroll view.
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
但这有效:
struct ContentView: View {
var body: some View {
ScrollView {
Text("Hello")
.preference(key: WidthPreferenceKey.self, value: 20)
}
.onPreferenceChange(WidthPreferenceKey.self) {
print($0)
}
}
}
Run Code Online (Sandbox Code Playgroud)
我知道我可以使用后一种方法来解决这个问题,但有时我在一个无法访问其父滚动视图的子视图中,但我仍然想记录一个首选项键。
关于如何onPreferenceChange在 a 中被调用的任何想法ScrollView?
注意:
Bound preference WidthPreferenceKey tried to update multiple times per frame.当我将函数放入滚动视图时,我得到了,这可能会解释发生了什么,但我无法弄清楚。
谢谢!
Kyo*_*ang 15
我一直试图找出这个问题很长一段时间并找到了如何处理它,尽管我使用的方式只是一种解决方法。
与标志一起使用
onAppear以ScrollView使其子项出现。
...
@State var isShowingContent = false
...
ScrollView {
if isShowingContent {
ContentView()
}
}
.onAppear {
self.isShowingContent = true
}
Run Code Online (Sandbox Code Playgroud)
或者,
用List它代替。
它具有滚动功能,您可以在 UI 方面使用自己的功能和 UITableView 外观对其进行自定义。最重要的是它按我们的预期工作。
[如果你有时间阅读更多]
让我谈谈我对这个问题的看法。
我已经证实,onPreferenceChange没有在所谓的自举里面放一个视图的时间ScrollView。我不确定这是否是正确的行为。但是,我认为这是错误的,因为ScrollView即使其中一些使用 PreferenceKey 在其中的视图之间传递任何数据,也必须能够包含任何视图。如果这是正确的行为,我们在创建自定义视图时很容易遇到麻烦。
让我们更详细地了解一下。
我想这ScrollView与其他容器视图(例如 List、(H/V)Stack)在引导时设置其子视图时的工作方式略有不同。换句话说,ScrollView会尝试以自己的方式绘制(或布置)孩子。不幸的是,这种方式会影响孩子的布局机制,正如我们所看到的那样不正确地工作。我们可以猜测调试视图中的以下消息发生了什么。
TestHPreferenceKey tried to update multiple times per frame.
这可能是一个证据,告诉我们在ScrollView为它的设置做一些事情时发生了孩子的更新。此时,可以猜测到 PreferenceKey 的更新已被忽略。
这就是为什么我试图将放置子视图放到onAppear.
我希望这对那些在 SwiftUI 上遇到各种问题的人有用。
transformPreference你可能只能在superView中读取它,但是你可以在设置后更改它。
struct ContentView: View {
var body: some View {
ScrollView {
VStack{
Text("Hello")
.preference(key: WidthPreferenceKey.self, value: 20)
}.transformPreference(WidthPreferenceKey.self, {
$0 = 30})
}.onPreferenceChange(WidthPreferenceKey.self) {
print($0)
}
}
}
Run Code Online (Sandbox Code Playgroud)
最后一个值是30现在。希望这是你想要的。
您可以从其他层读取:
ScrollView {
Text("Hello").preference(key: WidthPreferenceKey.self, value: CGFloat(40.0))
.backgroundPreferenceValue(WidthPreferenceKey.self) { x -> Color in
print(x)
return Color.clear
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
7178 次 |
| 最近记录: |