ios - 键盘出现后布局被破坏

标签 ios swift uicollectionview

我建立了一个表单,用户可以在其中写下他的报告。当我点击一个 textField 时,键盘出现并且 View 困惑,我无法弄清楚为什么会这样。我也多次收到此错误消息。有关我如何构建 View 的一些信息。此 collectionsView 的单元格也是 collectionViews,它显示显示的 View (具有白色背景色的部分)。 gif 末尾的浅蓝色(底部)是 homeContoller collectionView 的背景色。 buttonContainer 是 newReportCell 对象的一部分,它是 homeController collectionView 中的一个单元格。如果有人知道如何修复此错误,那将非常有帮助。

2018-08-21 14:28:53.772211+0200 TestApp[91209:4755287] The behavior of the UICollectionViewFlowLayout is not defined because: 2018-08-21 14:28:53.772389+0200 TestApp[91209:4755287] the item height must be less than the height of the UICollectionView minus the section insets top and bottom values, minus the content insets top and bottom values. 2018-08-21 14:28:53.772610+0200 TestApp[91209:4755287] The relevant UICollectionViewFlowLayout instance is , and it is attached to ; layer = ; contentOffset: {768, 0}; contentSize: {1536, 858}; adjustedContentInset: {0, 0, 263, 0}> collection view layout: . 2018-08-21 14:28:53.772728+0200 TestApp[91209:4755287] Make a symbolic breakpoint at UICollectionViewFlowLayoutBreakForInvalidSizes to catch this in the debugger.

import UIKit

class HomeController: UICollectionViewController, UICollectionViewDelegateFlowLayout{

    let cellId = "cellId"
    let cellId2 = "cellId2"
    let appTitles = ["Test" , "TestView"]
    var currentIndexPath = IndexPath(item: 0, section: 0)

    lazy var menuBar: MenuBar = {
        let mb = MenuBar()
        mb.homeController = self
        mb.translatesAutoresizingMaskIntoConstraints = false
        return mb
    }()

    override func viewDidLoad() {
        super.viewDidLoad()
        initView()
    }

    func initView() {           
        navigationItem.title = "Test"
        navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Logout", style: .plain, target: self, action: #selector(handleLogout))

        navigationController?.navigationBar.prefersLargeTitles = true


        setupMenuBar()
        setupCollectionView()
        setupMenuButtons()

        observeKeyboardNotifications()
    }

    func setupCollectionView() {

        if let flowLayout = collectionView?.collectionViewLayout as? UICollectionViewFlowLayout {
            flowLayout.scrollDirection = .horizontal
            flowLayout.minimumLineSpacing = 0
        }

        // blue background color
        collectionView?.backgroundColor = UIColor(r: 198, g: 225, b: 243)

        collectionView?.register(FeedCell.self, forCellWithReuseIdentifier: cellId)
        collectionView?.register(NewReportCell.self, forCellWithReuseIdentifier: cellId2)

        collectionView?.translatesAutoresizingMaskIntoConstraints = false
        collectionView?.topAnchor.constraint(equalTo: menuBar.bottomAnchor).isActive = true
        collectionView?.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
        collectionView?.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true
        collectionView?.heightAnchor.constraint(equalTo: view.heightAnchor, constant: -166).isActive =  true
        collectionView?.isPagingEnabled = true
    }

    func setupMenuButtons() {
        let synchroImage = UIImage(named: "synchronize")
        let synchroBarButtonItem = UIBarButtonItem(image: synchroImage, style: .plain, target: self, action: #selector(handleSync))
        navigationItem.rightBarButtonItems = [synchroBarButtonItem]
    }

    private func setTitleForIndex(index: Int) {
        navigationItem.title = appTitles[Int(index)]
        dismissKeyboard()
    }

    @objc func dismissKeyboard() {
        self.view.endEditing(true)
    }

    override func scrollViewDidScroll(_ scrollView: UIScrollView) {
        menuBar.horizontalBarLeadingAnchorConstraint?.constant = scrollView.contentOffset.x / CGFloat(appTitles.count)
    }

    override func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
        let index = targetContentOffset.pointee.x / view.frame.width

        let indexPath = IndexPath(item: Int(index), section: 0)
        currentIndexPath = indexPath
        menuBar.collectionView.selectItem(at: indexPath, animated: true, scrollPosition: [])

        setTitleForIndex(index: Int(index))
        self.invalidateLayoutForCell(index: Int(index))
    }

    func invalidateLayoutForCell(index: Int) {
        if index == 0 {
            self.feedCell?.invalidateLayout()
        } else {
            self.newReportCell?.invalidateLayout()
        }
    }

    override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return appTitles.count
    }

    override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        if indexPath.item == 0{
            let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as! FeedCell
            cell.homeController = self
            feedCell = cell
            return cell
        }
        else {
            let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId2, for: indexPath) as! NewReportCell
            cell.homeController = self
            newReportCell = cell
            return cell
        }
    }

    func pushViewController(controller: UICollectionViewController, animated: Bool) {
        navigationController?.pushViewController(controller, animated: animated)
    }

    func scrollToMenuIndex(menuIndex: Int) {
        let indexPath = IndexPath(item: menuIndex, section: 0)
        currentIndexPath = indexPath
        collectionView?.scrollToItem(at: indexPath, at: [], animated: true)

        setTitleForIndex(index: menuIndex)
        DispatchQueue.main.async {
        }
    }

    func invalidateLayout() {
        self.collectionView?.collectionViewLayout.invalidateLayout()


        DispatchQueue.main.async {
            self.collectionView?.scrollToItem(at: self.currentIndexPath, at: .centeredHorizontally, animated: true)
            self.menuBar.refreshView()
            self.feedCell?.invalidateLayout()
            self.newReportCell?.invalidateLayout()
        }
    }

    override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
        super.viewWillTransition(to: size, with: coordinator)
        invalidateLayout()
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        print(collectionView.frame.width, " - " , collectionView.frame.height)
        return CGSize(width: collectionView.frame.width, height: collectionView.frame.height)
    }


    private func setupMenuBar() {
        view.addSubview(menuBar)
        menuBar.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
        menuBar.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true
        menuBar.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true
        menuBar.heightAnchor.constraint(equalToConstant: 50).isActive = true
    }

    fileprivate func observeKeyboardNotifications() {
        NotificationCenter.default.addObserver(self, selector: #selector(keyboardShow), name: .UIKeyboardWillShow, object: nil)

        NotificationCenter.default.addObserver(self, selector: #selector(keyboardHide), name: .UIKeyboardWillHide, object: nil)
    }

    @objc func keyboardShow() {
        if(UIDevice.current.orientation == UIDeviceOrientation.landscapeLeft || UIDevice.current.orientation == UIDeviceOrientation.landscapeRight){
            UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 1, options: .curveEaseOut, animations: {
                self.view.frame = CGRect(x: 0, y: -150, width: self.view.frame.width, height: self.view.frame.height)
            }, completion: nil)
        }
        else {
            UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 1, options: .curveEaseOut, animations: {
                self.view.frame = CGRect(x: 0, y: -50, width: self.view.frame.width, height: self.view.frame.height)
            }, completion: nil)
        }
        print("keyboard shown")
    }

    @objc func keyboardHide() {
        UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 1, options: .curveEaseOut, animations: {
            self.view.frame = CGRect(x: 0, y: 0, width: self.view.frame.width, height: self.view.frame.height)
        }, completion: nil)
        print("keyboard hide")
    }

}

layout crashes when keyboard appears

最佳答案

func keyboardWillShow(notification: NSNotification) {            
    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
        self.view.frame.origin.y -= keyboardSize.height
    }            
}

func keyboardWillHide(notification: NSNotification) {
    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
        self.view.frame.origin.y += keyboardSize.height
    }

尝试在我的项目中使用这两个函数,它不会破坏你的布局

关于ios - 键盘出现后布局被破坏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51948888/

相关文章:

ios - awakeFromNib() 不适用于模拟指标

iOS - 检测 Blow into Mic 并转换结果! ( swift )

Swift 3 脚本 - 访问进程参数

ios - 如何在 Collection View 中为每个单元格添加 edgeInsets -Swift

ios - 如何连续发送 2 个请求

ios - 应用程序因内存压力而崩溃,我该如何解决它

ios - NSURLSession 错误处理

ios - UITableViewCell 类中的 PerfomSegue

ios - 如何访问存储在 UICollectionViewController 中的 Collection View Cell 中的变量

ios - 以编程方式加载和删除应用程序