我建立了一个表单,用户可以在其中写下他的报告。当我点击一个 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")
}
}
最佳答案
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/