如何解决完成多项选择后如何启用按钮以及如何禁用其他选择?
我认为有10种不同的选择。我要在做出10个选择中的任何一个时启用“ Devam Et”按钮。听起来很简单,但是关键部分如下...当我单击前8个按钮中的任何一个时,如果要选择后两个按钮,我想禁用它们;如果我选择了后两个选项中的任何一个,我也要禁用所有其他8个选项(如果已选择)。
前3个按钮配置行的代码如下...其余的与这些相同。
vstack{
HStack {
Button(action: {
self.tap1.toggle()
}) {
ZStack {
Rectangle()
.fill(self.tap1 ? Color(#colorLiteral(red: 0.9254902005,green: 0.2352941185,blue: 0.1019607857,alpha: 1)) : Color(#colorLiteral(red: 0.936548737,green: 0.936548737,blue: 0.936548737,alpha: 1)))
.frame(width: 25,height: 25)
if self.tap1 {
Image(systemName: "checkmark")
}
}.padding(.leading,40)
}
Spacer()
Text("Diyabet")
.font(.system(size: 20,weight: .regular,design: .rounded))
.padding(.trailing,200)
Spacer()
}.padding(.bottom,10)
HStack {
Button(action: {
self.tap2.toggle()
}) {
ZStack {
Rectangle()
.fill(self.tap2 ? Color(#colorLiteral(red: 0.9254902005,alpha: 1)))
.frame(width: 25,height: 25)
if self.tap2 {
Image(systemName: "checkmark")
}
}.padding(.leading,40)
}
Spacer()
Text("Yüksek Tansiyon")
.font(.system(size: 20,130)
Spacer()
}.padding(.bottom,10)
HStack {
Button(action: {
self.tap3.toggle()
}) {
ZStack {
Rectangle()
.fill(self.tap3 ? Color(#colorLiteral(red: 0.9254902005,height: 25)
if self.tap3 {
Image(systemName: "checkmark")
}
}.padding(.leading,40)
}
button1
}
“ Devam Et”按钮的代码如下...
var button1: some View{
return Button(action: {
if self.tap1 == true || self.tap2 == true || self.tap3 == true || self.tap4 == true || self.tap5 == true || self.tap6 == true || self.tap7 == true || self.tap8 == true {
self.tap11.toggle()
}
else if self.tap9 == true {
self.tap11.toggle()
}
else if self.tap10 == true {
self.tap11.toggle()
}
}) {
Text("Devam Et")
.font(.system(size: 20,design: .rounded))
.foregroundColor(Color.white)
.frame(width: 200,height: 30)
.padding()
.background(Color(#colorLiteral(red: 0.3101329505,green: 0.193462044,blue: 0.3823927939,alpha: 1)))
.cornerRadius(40)
.shadow(color: .gray,radius: 20.0,x: 20,y: 10)
.padding(.bottom,70)
}.background(
NavigationLink(destination: destinationView,isActive: $tap11) {
EmptyView()
}
.hidden()
)
}
@viewbuilder
var destinationView: some View {
if tap1 || tap2 || tap3 || tap4 || tap5 || tap6 || tap7 || tap8 || tap9 || tap10{
entrance5()
}
}
解决方法
TL; DR:结果视频:https://imgur.com/wRx2Ezg
好的,这是一个冗长的答案,在此之前,我将对您以前的一些代码进行评论:
将每个布尔值保留在各自的字段中并不是一个很好的选择,因为您注意到很难跟踪它们。相反,您可以使用某种结构来跟踪您提供的每个选择。
您还需要进行适当的状态跟踪,目前您需要3种状态:
- 标准状态:尚未选择任何内容。
- 多选状态:除独占选择外,可以有多个选择。
- 独家选择状态:在各自的组中只能选择一个。
您还需要将其集成到您的选择中,以确定您在列表中选择的种类。
最后但并非最不重要的一点,应在当前视图之外进行处理,例如在交互器中进行处理。
这是完整的代码,可以在Playgrounds中进行测试:
import SwiftUI
import PlaygroundSupport
enum ContentType {
case standard
case exclusive
}
enum ContentState {
case none
case multipleChoice
case exclusiveChoice
}
struct ContentChoice: Identifiable {
var id: String { title }
let title: String
let type: ContentType
var isSelected: Bool = false
var isDisabled: Bool = false
}
class ContentInteractor: ObservableObject,ContentChoiceViewDelegate {
@Published var choices: [ContentChoice] = []
@Published var state: ContentState = .none {
didSet {
print("state is now: \(state)")
switch state {
case .none:
exclusiveChoices.forEach { choices[$0].isDisabled = false }
standardChoices.forEach { choices[$0].isDisabled = false }
case .multipleChoice:
exclusiveChoices.forEach { choices[$0].isDisabled = true }
case .exclusiveChoice:
standardChoices.forEach { choices[$0].isDisabled = true }
}
}
}
private var exclusiveChoices: [Int] {
choices.indices.filter { choices[$0].type == .exclusive }
}
private var standardChoices: [Int] {
choices.indices.filter { choices[$0].type == .standard }
}
private var isExclusiveChoiceSelected: Bool {
choices.filter { $0.type == .standard && $0.isSelected }.count > 0
}
private var selectedMultipleChoiceCount: Int {
choices.filter { $0.type == .standard && $0.isSelected }.count
}
func didToggleChoice(_ choice: ContentChoice) {
guard let index = choices.firstIndex(where: { $0.id == choice.id }) else {
fatalError("No choice found with the given id.")
}
// This is where the whole algorithm lies.
switch state {
// Phase 1:
// If the user has not made any choice (state == .none),// Enabling a `.standard` choice should lock the `.exclusive` choices.
// And vice versa.
case .none:
choices[index].isSelected.toggle()
switch choice.type {
case .standard:
state = .multipleChoice
case .exclusive:
state = .exclusiveChoice
}
// Phase 2:
// If the user is in multiple choice state,// They can only select multiple choices. If any of the multiple choice
// is still selected,it should stay as is.
// If every choice is deselected,it should return the state to `.none`.
case .multipleChoice:
choices[index].isSelected.toggle()
switch choice.type {
case .standard:
if selectedMultipleChoiceCount == 0 {
state = .none
}
case .exclusive:
preconditionFailure("Unexpected choice selection.")
}
// Phase 3:
// If the user is in a not-answering state,// They can only change it within themselves.
// If every choice is deselected,it should return the state to `.none`.
// Also,every exclusive choice is,exclusive.
// Hence,if one of them is selected,the others should be deselected.
case .exclusiveChoice:
switch choice.type {
case .standard:
preconditionFailure("Unexpected choice selection.")
case .exclusive:
let isSelecting = !choices[index].isSelected
if isSelecting {
exclusiveChoices.forEach { choices[$0].isSelected = false }
} else {
state = .none
}
}
choices[index].isSelected.toggle()
}
}
func didSelectSubmit() {
print("Current selection:",choices.filter { $0.isSelected }.map { $0.title })
}
}
protocol ContentChoiceViewDelegate: AnyObject {
func didToggleChoice(_ choice: ContentChoice)
func didSelectSubmit()
}
struct ContentChoiceView: View {
let choice: ContentChoice
weak var delegate: ContentChoiceViewDelegate!
init(choice: ContentChoice,delegate: ContentChoiceViewDelegate) {
self.choice = choice
self.delegate = delegate
}
var body: some View {
HStack {
Button(action: {
self.delegate.didToggleChoice(self.choice)
}) {
ZStack {
Rectangle()
.fill(self.choice.isSelected ? Color(#colorLiteral(red: 0.9254902005,green: 0.2352941185,blue: 0.1019607857,alpha: 1)) : Color(#colorLiteral(red: 0.936548737,green: 0.936548737,blue: 0.936548737,alpha: 1)))
.frame(width: 25,height: 25)
if self.choice.isSelected {
Image(systemName: "checkmark")
}
}.padding(.leading,40)
}.disabled(self.choice.isDisabled)
Spacer()
Text(choice.title)
.font(.system(size: 20,weight: .regular,design: .rounded))
// .padding(.trailing,200)
Spacer()
}.padding(.bottom,10)
}
}
struct ContentView: View {
@ObservedObject var interactor: ContentInteractor
var body: some View {
VStack {
ForEach(interactor.choices) { choice in
ContentChoiceView(choice: choice,delegate: self.interactor)
}
Spacer()
submitButton
}.padding(.vertical,70)
}
var submitButton: some View {
Button(action: {
self.interactor.didSelectSubmit()
}) {
Text("Devam Et")
.font(.system(size: 20,design: .rounded))
.foregroundColor(Color.white)
.frame(width: 200,height: 30)
.padding()
.background(Color(#colorLiteral(red: 0.3101329505,green: 0.193462044,blue: 0.3823927939,alpha: 1)))
.cornerRadius(40)
.shadow(color: .gray,radius: 20.0,x: 20,y: 10)
}
}
}
let interactor = ContentInteractor()
["Diyabet","Yuksek Tansiyon","Astim"].forEach { title in
interactor.choices.append(ContentChoice(title: title,type: .standard))
}
["Soylememeyi Tercih Ederim","Hicbirini Gecirmedim"].forEach { title in
interactor.choices.append(ContentChoice(title: title,type: .exclusive))
}
let contentView = ContentView(interactor: interactor)
PlaygroundPage.current.setLiveView(contentView)
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。