我正在构建一个 SwitUI 表单。我需要绘制一些自定义滑块。为此,我创建了一个视图 (SliderView),并将其多次包含在表单中。我花了一些时间来管理 Binding 以在父视图中获取 Sliders 的值,但我能够做到 :-) 我无法理解的最大谜团是为什么我放置在孩子中的按钮视图,当它们嵌入到表单中时不起作用。它们在 VStack 中工作正常。这里的代码:
// SliderView.swift
import SwiftUI
struct SliderView: View {
var name: String
var min: Double
var max: Double
var step: Double
var defaultValue: Double
let numberFormatter: NumberFormatter = {
let formatter = NumberFormatter()
formatter.minimumFractionDigits = 0
formatter.maximumFractionDigits = 2
formatter.minimumIntegerDigits = 1
return formatter
}()
@Binding var selectedValue: Double
var body: some View {
HStack{
Text("\(name)")
Slider(value: $selectedValue, in: self.min...self.max, step: self.step)
Button(action: {
if (self.selectedValue - self.step) >= self.min{
self.selectedValue = self.selectedValue - self.step
}
}) {
Image(systemName:"minus.circle")
}
Text("\(numberFormatter.string(from: NSNumber(value: selectedValue)) ?? "")")
.padding(5)
.onAppear {
self.selectedValue = self.defaultValue
}
Button(action: {
if (self.selectedValue + self.step) <= self.max{
self.selectedValue = self.selectedValue + self.step
}
}) {
Image(systemName:"plus.circle")
}
}
}
}
struct SliderView_Previews: PreviewProvider {
@State static var myValue: Double = 1
static var previews: some View {
SliderView(name: "CPU", min: 1, max: 10, step: 0.5, defaultValue: 1, selectedValue: $myValue)
}
}
Run Code Online (Sandbox Code Playgroud)
现在,我正在构建的表单的一部分。代码编译,滑块工作,每个滑块的值都可以在父视图中看到。但是,逐步更新滑块的按钮不起作用(因为它们嵌入在表单中)
// SliderView.swift
import SwiftUI
struct SliderView: View {
var name: String
var min: Double
var max: Double
var step: Double
var defaultValue: Double
let numberFormatter: NumberFormatter = {
let formatter = NumberFormatter()
formatter.minimumFractionDigits = 0
formatter.maximumFractionDigits = 2
formatter.minimumIntegerDigits = 1
return formatter
}()
@Binding var selectedValue: Double
var body: some View {
HStack{
Text("\(name)")
Slider(value: $selectedValue, in: self.min...self.max, step: self.step)
Button(action: {
if (self.selectedValue - self.step) >= self.min{
self.selectedValue = self.selectedValue - self.step
}
}) {
Image(systemName:"minus.circle")
}
Text("\(numberFormatter.string(from: NSNumber(value: selectedValue)) ?? "")")
.padding(5)
.onAppear {
self.selectedValue = self.defaultValue
}
Button(action: {
if (self.selectedValue + self.step) <= self.max{
self.selectedValue = self.selectedValue + self.step
}
}) {
Image(systemName:"plus.circle")
}
}
}
}
struct SliderView_Previews: PreviewProvider {
@State static var myValue: Double = 1
static var previews: some View {
SliderView(name: "CPU", min: 1, max: 10, step: 0.5, defaultValue: 1, selectedValue: $myValue)
}
}
Run Code Online (Sandbox Code Playgroud)
只需在上面的代码中用“VStack”替换“Form”,按钮就可以正常工作。任何人都可以透露一些信息吗?我认为是关于表单中不同层的问题。当我尝试单击按钮时,似乎单击了带有滑块的整行,但没有任何反应。我在 MacOS 10.15 beta (19A558d) 中使用 Xcode 11 GM 提前致谢!
pbc*_*pbc 20
据我所知,当表单行包含接受点击手势的视图(例如按钮)时,它们的行为会有所不同。当该行包含一个 Button 时,当用户点击该按钮时,同一行中的所有其他内容也会收到点击手势。所以在你上面的例子中,并不是你的按钮不起作用,实际发生的是它们都在接收点击手势并执行它们的动作,但是由于你的代码中的逻辑有效地取消了另一个的效果,它看起来好像它们不工作。
为了帮助证明这一点,这里是我写的一些测试代码:
@State var count1 = 0
@State var count2 = 0
func buttonTest() -> some View {
HStack {
Button(action: {
self.count1 += 1
}) {
Text("Button 1: \(count1)")
}
Spacer()
Button(action: {
self.count2 += 1
}) {
Text("Button 2: \(count2)")
}
}
}
var body: some View {
VStack {
buttonTest()
Form {
Section(header: Text("Test")) {
buttonTest()
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
如果您点击表单上方的任一按钮,它们会按预期独立工作,仅增加自己的计数,但如果您点击表单中的任一按钮或行中的任何其他位置,则两个按钮的操作都会执行,并且两个计数都会增加。
我不确定 Apple 为什么要这样做,但我也在努力寻找解决此问题的方法。
编辑
感谢Shauket Sheikh,有一个解决方案,但它使代码重用不太优雅。
所以当Button在Form中时,需要将代码放入.onTapGesturehandler中,但是如果Button在Form之外,则需要action:handler中的代码。
我真的希望这不是 Apple 对 Forms 的长期立场:它违背了一次编写,到处使用的理念。
小智 15
尝试向表单中的按钮添加一个 buttonStyle 修饰符。这对我有用:
Button(action: {}, label: {Text("Test")})
.buttonStyle(PlainButtonStyle())
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
6159 次 |
| 最近记录: |