Tabview 无法正确切换标签
Tabview not switching tabs properly
我有一个用于创建自动幻灯片的标签视图(页面样式)。由于某些奇怪的原因,每张幻灯片都没有分配给 currentIndex。使用 tabview 提供的默认点控件,定时器或手动切换选项卡都不起作用。
如果我将标签设置为 selectedIndex,tabview 将默认为第一张幻灯片。
控制台没有错误。
非常感谢任何帮助!
struct HomeView: View {
@EnvironmentObject private var hvm: HomeViewModel
@State private var selectedFilter: String = "Popular"
@State private var selectedMedia: MediaModelResult? = nil
@State private var showDetailView: Bool = false
@State private var currentIndex: Int = 0
@State var isFilterSelected: Bool = true
@Namespace var animation
private let timer = Timer.publish(every: 3, on: .main, in: .common).autoconnect()
var body: some View {
NavigationView {
ZStack {
Color.theme.background.ignoresSafeArea()
VStack {
header
VStack(alignment: .leading, spacing: 15) {
Text("Upcoming Movies")
.foregroundColor(Color.theme.secondaryAccent)
.font(.subheadline)
.padding(.leading, 15)
TabView(selection: $currentIndex) {
ForEach(hvm.upcomingFilms) { film in
MediaImageView(mediaPath: film, poster: false)
.scaledToFill()
.tag(film)
}
}
.tabViewStyle(PageTabViewStyle())
.clipShape(RoundedRectangle(cornerRadius: 5))
.padding(.horizontal, 15)
.frame(width: UIScreen.main.bounds.width, height: 180)
.onReceive(timer, perform: { _ in
withAnimation(.default) {
currentIndex = currentIndex < hvm.upcomingFilms.count ? currentIndex + 1 : 0
}
})
}
scrollViewContent
}
}
.preferredColorScheme(.dark)
.navigationBarHidden(true)
}
}
}
struct MediaImageView: View {
@StateObject var mivm: MediaImageViewModel
var poster: Bool
init(mediaPath: MediaModelResult, poster: Bool) {
self.poster = poster
_mivm = StateObject(wrappedValue: MediaImageViewModel(mediaPath: mediaPath))
}
var body: some View {
if poster {
ZStack {
if let image = mivm.poster {
Image(uiImage: image)
.resizable()
.scaledToFit()
} else if mivm.isLoading {
ProgressView()
}
}
} else {
ZStack {
if let image = mivm.backdrop {
Image(uiImage: image)
.resizable()
} else if mivm.isLoading {
ProgressView()
}
}
}
}
}
class HomeViewModel: ObservableObject {
@Published var tabBarImageNames = ["house", "rectangle.stack", "clock.arrow.circlepath", "magnifyingglass"]
@Published var filterTitles = ["Popular Now", "Top Rated", "New"]
@Published var popularFilms: [MediaModelResult] = []
@Published var topRatedFilms: [MediaModelResult] = []
@Published var upcomingFilms: [MediaModelResult] = []
@Published var popularTV: [MediaModelResult] = []
@Published var topRatedTV: [MediaModelResult] = []
private let dataService = MediaDataService()
private var cancellables = Set<AnyCancellable>()
init() {
addSubscribers()
}
func addSubscribers() {
dataService.$popularFilms
.sink { [weak self] (returnedFilms) in
self?.popularFilms = returnedFilms
}
.store(in: &cancellables)
dataService.$topRatedFilms
.sink { [weak self] (returnedFilms) in
self?.topRatedFilms = returnedFilms
}
.store(in: &cancellables)
dataService.$upcomingFilms
.sink { [weak self] (returnedFilms) in
self?.upcomingFilms = returnedFilms
}
.store(in: &cancellables)
dataService.$popularTV
.sink { [weak self] (returnedFilms) in
self?.popularTV = returnedFilms
}
.store(in: &cancellables)
dataService.$topRatedTV
.sink { [weak self] (returnedFilms) in
self?.topRatedTV = returnedFilms
}
.store(in: &cancellables)
}
}
解决方案:
TabView(selection: $currentIndex) {
ForEach(0..<hvm.upcomingFilms.count) { film in
MediaImageView(mediaPath: hvm.upcomingFilms[film], poster: false)
.scaledToFill()
}
}
我有一个用于创建自动幻灯片的标签视图(页面样式)。由于某些奇怪的原因,每张幻灯片都没有分配给 currentIndex。使用 tabview 提供的默认点控件,定时器或手动切换选项卡都不起作用。
如果我将标签设置为 selectedIndex,tabview 将默认为第一张幻灯片。 控制台没有错误。 非常感谢任何帮助!
struct HomeView: View {
@EnvironmentObject private var hvm: HomeViewModel
@State private var selectedFilter: String = "Popular"
@State private var selectedMedia: MediaModelResult? = nil
@State private var showDetailView: Bool = false
@State private var currentIndex: Int = 0
@State var isFilterSelected: Bool = true
@Namespace var animation
private let timer = Timer.publish(every: 3, on: .main, in: .common).autoconnect()
var body: some View {
NavigationView {
ZStack {
Color.theme.background.ignoresSafeArea()
VStack {
header
VStack(alignment: .leading, spacing: 15) {
Text("Upcoming Movies")
.foregroundColor(Color.theme.secondaryAccent)
.font(.subheadline)
.padding(.leading, 15)
TabView(selection: $currentIndex) {
ForEach(hvm.upcomingFilms) { film in
MediaImageView(mediaPath: film, poster: false)
.scaledToFill()
.tag(film)
}
}
.tabViewStyle(PageTabViewStyle())
.clipShape(RoundedRectangle(cornerRadius: 5))
.padding(.horizontal, 15)
.frame(width: UIScreen.main.bounds.width, height: 180)
.onReceive(timer, perform: { _ in
withAnimation(.default) {
currentIndex = currentIndex < hvm.upcomingFilms.count ? currentIndex + 1 : 0
}
})
}
scrollViewContent
}
}
.preferredColorScheme(.dark)
.navigationBarHidden(true)
}
}
}
struct MediaImageView: View {
@StateObject var mivm: MediaImageViewModel
var poster: Bool
init(mediaPath: MediaModelResult, poster: Bool) {
self.poster = poster
_mivm = StateObject(wrappedValue: MediaImageViewModel(mediaPath: mediaPath))
}
var body: some View {
if poster {
ZStack {
if let image = mivm.poster {
Image(uiImage: image)
.resizable()
.scaledToFit()
} else if mivm.isLoading {
ProgressView()
}
}
} else {
ZStack {
if let image = mivm.backdrop {
Image(uiImage: image)
.resizable()
} else if mivm.isLoading {
ProgressView()
}
}
}
}
}
class HomeViewModel: ObservableObject {
@Published var tabBarImageNames = ["house", "rectangle.stack", "clock.arrow.circlepath", "magnifyingglass"]
@Published var filterTitles = ["Popular Now", "Top Rated", "New"]
@Published var popularFilms: [MediaModelResult] = []
@Published var topRatedFilms: [MediaModelResult] = []
@Published var upcomingFilms: [MediaModelResult] = []
@Published var popularTV: [MediaModelResult] = []
@Published var topRatedTV: [MediaModelResult] = []
private let dataService = MediaDataService()
private var cancellables = Set<AnyCancellable>()
init() {
addSubscribers()
}
func addSubscribers() {
dataService.$popularFilms
.sink { [weak self] (returnedFilms) in
self?.popularFilms = returnedFilms
}
.store(in: &cancellables)
dataService.$topRatedFilms
.sink { [weak self] (returnedFilms) in
self?.topRatedFilms = returnedFilms
}
.store(in: &cancellables)
dataService.$upcomingFilms
.sink { [weak self] (returnedFilms) in
self?.upcomingFilms = returnedFilms
}
.store(in: &cancellables)
dataService.$popularTV
.sink { [weak self] (returnedFilms) in
self?.popularTV = returnedFilms
}
.store(in: &cancellables)
dataService.$topRatedTV
.sink { [weak self] (returnedFilms) in
self?.topRatedTV = returnedFilms
}
.store(in: &cancellables)
}
}
解决方案:
TabView(selection: $currentIndex) {
ForEach(0..<hvm.upcomingFilms.count) { film in
MediaImageView(mediaPath: hvm.upcomingFilms[film], poster: false)
.scaledToFill()
}
}