简体   繁体   中英

Keyboard dismiss very buggy on tableview interactive

I have a textfield inside tableviewcontroller which is inside tabbarcontroller when i drag the keyboard down it lags right before dismiss. I am using the interactive mode so keyboard dismisses on drag.

class TempTableViewController: UITableViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        tableView.keyboardDismissMode = .interactive
        self.clearsSelectionOnViewWillAppear = false
        tableView.register(TitleTableViewCell.self, forCellReuseIdentifier: "reuseIdentifier")
    }


    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 1
    }


    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "reuseIdentifier", for: indexPath) as! TitleTableViewCell
        return cell
    }

    override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return UITableView.automaticDimension
    }

    override func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
        return UITableView.automaticDimension
    }
}

my tableviewcell has a uitextfield. however when i drag the keyboard down it lags before being dismissed

class TitleTableViewCell: UITableViewCell {


    let titleView: UITextField = {
       let textView = UITextField()
        textView.text = "Add your title ... "
        textView.font = UIFont.preferredFont(forTextStyle: .body)
//        textView.sizeToFit()
//        textView.isScrollEnabled = false
        textView.translatesAutoresizingMaskIntoConstraints=false
        return textView
    }()

    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)

        self.contentView.addSubview(titleView)
        setTitleViewConstraints()
    }

    required init?(coder: NSCoder) {
        super.init(coder: coder)
    }

    func setTitleViewConstraints(){
        titleView.leadingAnchor.constraint(equalTo: self.contentView.leadingAnchor,constant: 10).isActive=true
        titleView.trailingAnchor.constraint(equalTo: self.contentView.trailingAnchor,constant: -10).isActive=true
        titleView.topAnchor.constraint(equalTo: self.contentView.topAnchor, constant: 10).isActive=true
        titleView.bottomAnchor.constraint(equalTo: self.contentView.bottomAnchor,constant: -10).isActive=true
    }

}

class tabBarViewController: UITabBarController, UITabBarControllerDelegate {

    override func viewDidLoad() {
        super.viewDidLoad()
        let homeViewController = HomeViewController()
        homeViewController.tabBarItem = UITabBarItem(title: nil, image: UIImage(named: "home-tab")?.withRenderingMode(.alwaysOriginal), selectedImage: nil)
        let discoverViewController = DiscoverViewController()
        discoverViewController.tabBarItem = UITabBarItem(title: nil, image: UIImage(named: "discover-tab")?.withRenderingMode(.alwaysOriginal), selectedImage: nil)
        let notificationViewController = NotificationViewController()
        notificationViewController.tabBarItem = UITabBarItem(title: nil, image: UIImage(named: "notification-tab")?.withRenderingMode(.alwaysOriginal), selectedImage: nil)
        let tempViewController = TempTableViewController()
        tempViewController.tabBarItem = UITabBarItem(title: nil, image: UIImage(named: "profile-tab")?.withRenderingMode(.alwaysOriginal), selectedImage: nil)


        let tabBarList = [homeViewController, discoverViewController,notificationViewController,tempViewController ]

            self.viewControllers = tabBarList.map { viewController in

            return UINavigationController(rootViewController: viewController)

        }
    }

}

this is the appdelegate class where tabbarcontroller is selected based on user credentials

class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?
    var handle: AuthStateDidChangeListenerHandle?

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        FirebaseApp.configure()
        UINavigationBar.appearance().isOpaque = false
        UINavigationBar.appearance().backgroundColor = .white
        window = UIWindow(frame: UIScreen.main.bounds)
        checkUserStatus()
        return true
    }

    func checkUserStatus(){
        window?.backgroundColor = UIColor.white
        self.setupRootViewController(viewController: UIViewController())
        handle = Auth.auth().addStateDidChangeListener {[weak self] auth,user in
            if(user != nil){
                self?.setupRootViewController(viewController: tabBarViewController())
            }else{
                self?.setupRootViewController(viewController: UINavigationController(rootViewController: WelcomeViewController()))
            }
        }
    }
    private func setupRootViewController(viewController: UIViewController) {
        self.window!.rootViewController = viewController
        self.window!.makeKeyAndVisible()
    }

在此处输入图片说明

I launched your application with iOS 12 and it works correctly.

This solution may help you with iOS 13 .

1) Add the observer in viewDidLoad()

override func viewDidLoad() {
    ...

    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(notification:)), name: UIResponder.keyboardWillHideNotification, object: nil)
}

2) Add function getKeyboardWindow()

private func getKeyboardWindow() -> UIWindow? {

    for window in UIApplication.shared.windows {

        if (NSStringFromClass(type(of: window).self) == "UIRemoteKeyboardWindow") {
            return window
        }
    }

    return nil
}

3) Add function keyboardWillHide(notification:)

@objc private func keyboardWillHide(notification: Notification) {

    guard let keyboardWindow: UIWindow = getKeyboardWindow() else { return }

    let screenWidth: CGFloat = UIScreen.main.bounds.width
    let screenHeight: CGFloat = UIScreen.main.bounds.height

    keyboardWindow.frame = CGRect(x: 0, y: 50, width: screenWidth, height: screenHeight)
}

PS However, I don't like to fix issues this way.

But in this case, I don't know a more elegant solution.

在此处输入图片说明

doe,

What you are doing is right, I don't see that as an issue , even contacts app have the same feature like yours (ie text field in table view). Contact app also behaves the same way

Find the comparison screen recording of contact app and yours,

通讯录应用 . 你的应用

If you still want to fix it, I would suggest to remove auto-correction, If your requirement allows.

textView.autocorrectionType = .no

Because tableviews inherit from ScrollViews you can override a scrollview method "scrollViewWillEndDragging" and call endEditing(true)

  override func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
                self.view.endEditing(true)

        }

and you can even do more you can detect when the user scroll up or down using the velocity parameter of the function signature like this :

up

 override func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
        if(velocity.y > 0){
            self.view.endEditing(true)
            self.view.layoutIfNeeded()
        }
    }

down

 override func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
            if(velocity.y < 0){
                self.view.endEditing(true)
                self.view.layoutIfNeeded()
            }
        }

您可以尝试设置空视图textView.inputAccessoryView = UIView()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM