键盘调用TabBar SwiftUI 2.0中其他视图的出现

时间:2020-09-18 12:36:14

标签: swift keyboard swiftui uitabbarcontroller tabview

我在SwiftUI 2.0和Xcode 12中使用UITabBarController,但似乎键盘情况下出现一些意外行为。从下面的GIF中可以看到,其他2个标签的视图的OnAppear出现在键盘出现在第一个标签中时。由于出现了我写的API调用,因此导致了问题。

此外,有什么方法可以关闭Xcode 12的默认视图偏移行为。

enter image description here

这是我的Content View代码。

struct ContentView: View {
    @State private var index:Int = 0
    var menuItems:[String] = ["Item 1", "Item 2", "Item 3"]
    var body: some View {
        NavigationView(content: {
            ZStack{
                MyTabView(selectedIndex: self.$index)
                    .view(item: self.item1) {
                        NewView(title: "Hello1").navigationBarTitle("")
                            .navigationBarHidden(true)
                    }
                    .view(item: self.item2) {
                        NewView(title: "Hello2").navigationBarTitle("")
                            .navigationBarHidden(true)
                    }
                    .view(item: self.item3) {
                        NewView(title: "Hello3").navigationBarTitle("")
                            .navigationBarHidden(true)
                    }
            }.navigationBarHidden(true)
            .navigationBarTitle("")
        })
    }
    
    var item1:MyTabItem {
        
        var item = MyTabItem()
        item.imageName = "pencil.circle"
        item.selectedImageName = "pencil.circle.fill"
        return item
    }
    
    var item2:MyTabItem {
        var item = MyTabItem()
        item.imageName = "pencil.circle"
        item.selectedImageName = "pencil.circle.fill"
        return item
    }
    
    var item3:MyTabItem {
        var item = MyTabItem()
        item.imageName = "pencil.circle"
        item.selectedImageName = "pencil.circle.fill"
        return item
    }
}


struct NewView:View {
    @State var text:String = ""
    var title:String
    var body: some View {
        VStack {
            Spacer()
            Text("Hello")
            TextField(title, text: self.$text)
                .textFieldStyle(RoundedBorderTextFieldStyle())
            
        }.padding()
        .onAppear {
            debugPrint("OnApper \(self.title)")
        }
    }
}

这是CustomTabView的代码。

class MyTabViewViewModel:ObservableObject {
    var controllers: [UIViewController] = []
    var tabItems:[MyTabItem] = []
}

struct MyTabItem {
    var imageName:String = ""
    var selectedImageName:String = ""
    var hasDarkModeSupport:Bool = true
    var image:UIImage?
    var selectedImage:UIImage?
}

struct MyTabView: UIViewControllerRepresentable {
    
    var viewModel:MyTabViewViewModel = MyTabViewViewModel()
    
    @Binding var selectedIndex: Int
    
    func makeUIViewController(context: Context) -> UITabBarController {
        let tabBarController = UITabBarController()
        tabBarController.viewControllers = self.viewModel.controllers
        tabBarController.delegate = context.coordinator
        tabBarController.selectedIndex = 0
        
        let appearance = tabBarController.tabBar.standardAppearance
        appearance.shadowImage = nil
        appearance.shadowColor = nil
        appearance.backgroundEffect = nil
        tabBarController.tabBar.standardAppearance = appearance
        
        tabBarController.tabBar.shadowImage = UIImage()
        tabBarController.tabBar.backgroundImage = UIImage()
        tabBarController.tabBar.layer.shadowPath = UIBezierPath(rect: tabBarController.tabBar.bounds).cgPath
        tabBarController.tabBar.layer.shadowOffset = CGSize.init(width: 0, height: -3)
        tabBarController.tabBar.layer.shadowRadius = 5
        tabBarController.tabBar.layer.shadowColor = UIColor.black.cgColor
        tabBarController.tabBar.layer.shadowOpacity = 0.25
        tabBarController.tabBar.backgroundColor = UIColor.white
        tabBarController.tabBar.barTintColor = UIColor.white
        
        self.updateTabItems(forTabBarController: tabBarController)
        
        return tabBarController
    }
    
    func updateUIViewController(_ tabBarController: UITabBarController, context: Context) {
        tabBarController.selectedIndex = selectedIndex
        self.updateTabItems(forTabBarController: tabBarController)
    }
    
    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }
    
    func updateTabItems(forTabBarController tabBarController:UITabBarController) {
        let isDarkModeEnable:Bool = tabBarController.traitCollection.userInterfaceStyle == .dark
        for (index, tabItem) in self.viewModel.tabItems.enumerated() {
            
            tabBarController.tabBar.items?[index].title = ""
            
            if let image = tabItem.image {
                tabBarController.tabBar.items?[index].image = image
                if let selectedImage = tabItem.selectedImage {
                    tabBarController.tabBar.items?[index].selectedImage = selectedImage
                }
            } else {
                if tabItem.hasDarkModeSupport && isDarkModeEnable {
                    if let image = UIImage.init(systemName: "\(tabItem.imageName)-dark") {
                        tabBarController.tabBar.items?[index].image = image
                    } else if let image = UIImage.init(systemName: tabItem.imageName) {
                        tabBarController.tabBar.items?[index].image = image
                    }
                    if let selectedImage = UIImage.init(systemName: "\(tabItem.selectedImageName)-dark") {
                        tabBarController.tabBar.items?[index].selectedImage = selectedImage
                    } else if let selectedImage = UIImage.init(systemName: tabItem.selectedImageName) {
                        tabBarController.tabBar.items?[index].selectedImage = selectedImage
                    }
                } else {
                    if let image = UIImage.init(systemName: tabItem.imageName) {
                        tabBarController.tabBar.items?[index].image = image
                    }
                    if let selectedImage = UIImage.init(systemName: tabItem.selectedImageName) {
                        tabBarController.tabBar.items?[index].selectedImage = selectedImage
                    }
                }
            }
        }
    }
    
    class Coordinator: NSObject, UITabBarControllerDelegate {
        var parent: MyTabView
        
        init(_ tabBarController: MyTabView) {
            self.parent = tabBarController
        }
        
        func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) {
            parent.selectedIndex = tabBarController.selectedIndex
        }
    }
    
    func view<HostedView:View>(item:MyTabItem, @ViewBuilder sheet: @escaping () -> HostedView) -> MyTabView {
        self.viewModel.controllers.append(UIHostingController.init(rootView: sheet()))
        self.viewModel.tabItems.append(item)
        return self
    }
}

1 个答案:

答案 0 :(得分:1)

我自己遇到相同的问题

“笨拙”的解决方法是将NewView.body包装在列表中:

    @State var text:String = ""
    var title:String
    var body: some View {
        List {
            VStack {
                Spacer()
                Text("Hello")
                TextField(title, text: self.$text)
                    .textFieldStyle(RoundedBorderTextFieldStyle())
                
            }.padding()
            .onAppear {
                debugPrint("OnApper \(self.title)")
            }
        }
    }
}

也可以使用LazyVStack,但由于我的项目目标是13.x,所以没有对其进行测试

此处是同一问题OnAppear calls unexpectedly when Keyboard Appears in SwiftUI