我建立了一个表格,用户可以在其中写下他的报告。当我单击textField时,将出现键盘,并且视图被弄乱了,我无法弄清为什么会这样。我也多次收到此错误消息。有关如何构建视图的一些信息。此collectionsView的单元格也是collectionViews,它们显示显示的视图(具有白色背景颜色的部分)。 gif末尾的浅蓝色(底部)是homeContoller collectionView的背景色。 buttonContainer是newReportCell对象的一部分,该对象是homeController collectionView内部的单元格。如果有人对如何解决此错误有个想法,那将非常有帮助。
2018-08-21 14:28:53.772211 + 0200 TestApp [91209:4755287] 未定义UICollectionViewFlowLayout的行为,因为: 2018-08-21 14:28:53.772389 + 0200 TestApp [91209:4755287] 项目高度必须小于UICollectionView的高度 减去该部分可插入顶部和底部的值,减去内容 插入顶部和底部值。 2018-08-21 14:28:53.772610 + 0200 TestApp [91209:4755287]相关 UICollectionViewFlowLayout实例为,并附加到; 层=; contentOffset:{768,0}; contentSize:{1536,858}; AdjustedContentInset:{0,0,263,0}> 集合视图布局:。 2018-08-21 14:28:53.772728 + 0200 TestApp [91209:4755287] 在以下位置建立符号断点 UICollectionViewFlowLayoutBreakForInvalidSizes可以在 调试器。
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")
}
}
答案 0 :(得分:1)
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
}
尝试这两个功能可以在我的项目中使用,并且不会破坏您的布局
答案 1 :(得分:0)
希望这对您有帮助
要管理此问题,建议您使用IQKeyboardManagerSwift,它将处理您的键盘和文本字段。
答案 2 :(得分:0)
我想出了解决问题的方法。我将Mahesh Dangar的答案与Eduardo Irias(ios - How to get the height of Keyboard?)的答案结合在一起。当文本字段之一将pickerView作为inputView时,这将考虑安全区域并避免某些问题。视图将调整为键盘的高度。
var lastKeyboardHeight = CGFloat(0)
fileprivate func observeKeyboardNotifications() {
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: .UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name: .UIKeyboardWillHide, object: nil)
}
@objc func keyboardWillShow(notification: NSNotification) {
guard let keyboardFrame = notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue else {
return
}
let keyboardHeight: CGFloat
if #available(iOS 11.0, *) {
keyboardHeight = keyboardFrame.cgRectValue.height - self.view.safeAreaInsets.bottom
} else {
keyboardHeight = keyboardFrame.cgRectValue.height
}
if lastKeyboardHeight != keyboardHeight {
self.view.frame.origin.y += lastKeyboardHeight
}
else {
return
}
self.view.frame.origin.y -= keyboardHeight
lastKeyboardHeight = keyboardHeight
}
@objc func keyboardWillHide(notification: NSNotification) {
guard let keyboardFrame = notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue else {
return
}
let keyboardHeight: CGFloat
if #available(iOS 11.0, *) {
keyboardHeight = keyboardFrame.cgRectValue.height - self.view.safeAreaInsets.bottom
} else {
keyboardHeight = keyboardFrame.cgRectValue.height
}
self.view.frame.origin.y += keyboardHeight
lastKeyboardHeight = 0
}