내가 만든 뷰를 통해 ForEach 루프는 필요한 변수 계산 내에서 ForEach 자체 즉 나는 응용 프로그램을 필요로 반응하는 동적 계산과 변경 UI 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)
}
}
}
고 뷰 모델을 관찰할 것입니다:
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
}
}
기본적으로,버튼을에서 로그인 형태 그 자체를 설정 시점의 isActive 속성을 true 로 설정할 수 있습니다. 우리는 듣는 이를 위해서 TabBarViewModel 설정 activeFormIndex 니다. 이 인덱스는 다음에 사용되는 ForEach 다. 기본적으로,에 따라 선택하는 인덱스,내가 생성 할 필요가 더 많거나 적은 간격 장치에서 AnimatedTabSelector 보기입니다.
그러나 하 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)
각각합니다.
추가 브레이크 포인트에서 새로운 게시자가 선언하고 그것은 참으로 업데이트되고 있으로 예상된 수치입니다. 그러나보기는 여전히 실패한 변화를 반영하는 값