मैं एक देखने के माध्यम से बनाई गई एक ForEach पाश की जरूरत है, जो लेने के लिए एक चर गिनती के भीतर ForEach ही यानी मैं app की जरूरत के लिए प्रतिक्रिया करने के लिए एक गतिशील गिनती और यूआई बदलें accoridngly.
यहाँ देखें, मैं कोशिश कर रहा हूँ को संशोधित करने के लिए:
struct AnimatedTabSelector: View {
let buttonDimensions: CGFloat
@ObservedObject var tabBarViewModel: TabBarViewModel
var body: some View {
HStack {
Spacer().frame(maxWidth: .infinity).frame(height: 20)
.background(Color.red)
ForEach(1..<tabBarViewModel.activeFormIndex + 1) { _ in
Spacer().frame(maxWidth: buttonDimensions).frame(height: 20)
.background(Color.blue)
Spacer().frame(maxWidth: .infinity).frame(height: 20)
.background(Color.green)
}
Circle().frame(
width: buttonDimensions,
height: buttonDimensions)
.foregroundColor(
tabBarViewModel.activeForm.loginFormViewModel.colorScheme
)
ForEach(1..<tabBarViewModel.loginForms.count - tabBarViewModel.activeFormIndex) { _ in
Spacer().frame(maxWidth: .infinity).frame(height: 20)
.background(Color.red)
Spacer().frame(maxWidth: buttonDimensions).frame(height: 20)
.background(Color.blue)
}
Spacer().frame(maxWidth: .infinity).frame(height: 20)
.background(Color.gray)
}
}
}
और viewModel मैं देख रहा हूं:
class TabBarViewModel: ObservableObject, TabBarCompatible {
var loginForms: [LoginForm]
@Published var activeForm: LoginForm
@Published var activeFormIndex = 0
private var cancellables = Set<AnyCancellable>()
init(loginForms: [LoginForm]) {
self.loginForms = loginForms
self.activeForm = loginForms[0] /// First form is always active to begin
setUpPublisher()
}
func setUpPublisher() {
for i in 0..<loginForms.count {
loginForms[i].loginFormViewModel.$isActive.sink { isActive in
if isActive {
self.activeForm = self.loginForms[i]
self.activeFormIndex = i
}
}
.store(in: &cancellables)
}
}
}
और अंत में loginFormViewModel:
class LoginFormViewModel: ObservableObject {
@Published var isActive: Bool
let name: String
let icon: Image
let colorScheme: Color
init(isActive: Bool = false, name: String, icon: Image, colorScheme: Color) {
self.isActive = isActive
self.name = name
self.icon = icon
self.colorScheme = colorScheme
}
}
मूल रूप से, एक बटन पर लॉग इन के रूप में ही सेट अपने viewModel के isActive संपत्ति के लिए सच है । हम सुनने के लिए इस में TabBarViewModel और सेट activeFormIndex तदनुसार. इस सूचकांक में प्रयोग किया जाता है तो में ForEach पाश है. अनिवार्य रूप से, के आधार पर सूचकांक चयनित है, मैं की जरूरत है उत्पन्न करने के लिए और अधिक या कम spacers में AnimatedTabSelector देखें.
हालांकि, whilst activeIndex चर जा रहा है सही ढंग से अद्यतन, ForEach प्रतीत नहीं होता है करने के लिए प्रतिक्रिया.
अद्यतन:
के AnimatedTabSelector घोषित किया जाता है के भाग के रूप में इस समग्र दृष्टिकोण:
struct TabIconsView: View {
struct Constants {
static let buttonDimensions: CGFloat = 50
static let buttonIconSize: CGFloat = 25
static let activeButtonColot = Color.white
static let disabledButtonColor = Color.init(white: 0.8)
struct Animation {
static let stiffness: CGFloat = 330
static let damping: CGFloat = 22
static let velocity: CGFloat = 7
}
}
@ObservedObject var tabBarViewModel: TabBarViewModel
var body: some View {
ZStack {
AnimatedTabSelector(
buttonDimensions: Constants.buttonDimensions,
tabBarViewModel: tabBarViewModel)
HStack {
Spacer()
ForEach(tabBarViewModel.loginForms) { loginForm in
Button(action: {
loginForm.loginFormViewModel.isActive = true
}) {
loginForm.loginFormViewModel.icon
.font(.system(size: Constants.buttonIconSize))
.foregroundColor(
tabBarViewModel.activeForm.id == loginForm.id ? Constants.activeButtonColot : Constants.disabledButtonColor
)
}
.frame(width: Constants.buttonDimensions, height: Constants.buttonDimensions)
Spacer()
}
}
}
.animation(Animation.interpolatingSpring(
stiffness: Constants.Animation.stiffness,
damping: Constants.Animation.damping,
initialVelocity: Constants.Animation.velocity)
)
}
}
अद्यतन:
मैं करने की कोशिश की एक और तरीका जोड़ने के द्वारा एक और प्रकाशित करने के लिए AnimatedTabSelector खुद की जाँच करने के लिए मूल्यों है कि वास्तव में कर रहे हैं अद्यतन किया जा रहा है के अनुसार. तो के अंत में HStack इस दृश्य में मैं जोड़ा गया:
.onAppear {
tabBarViewModel.$activeFormIndex.sink { index in
self.preCircleSpacers = index + 1
self.postCircleSpacers = tabBarViewModel.loginForms.count - index
}
.store(in: &cancellables)
}
और बेशक, मैं निम्न चर के लिए यह देखें:
@State var preCircleSpacers = 1
@State var postCircleSpacers = 6
@State var cancellables = Set<AnyCancellable>()
फिर में ForEach छोरों मैं करने के लिए बदल गया:
ForEach(1..<preCircleSpacers)
और
ForEach(1..<postCircleSpacers)
क्रमश:.
मैं जोड़ा गया एक को तोड़ने बिंदु में नए प्रकाशक घोषणा की है और यह वास्तव में किया जा रहा है के साथ अद्यतन की उम्मीद है और आंकड़े. लेकिन देखने में अभी भी असफल को प्रतिबिंबित करने के लिए मूल्यों में परिवर्तन