在endEditing之后,UICollectionViewController页脚没有正确地重新定位自己
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在endEditing之后,UICollectionViewController页脚没有正确地重新定位自己相关的知识,希望对你有一定的参考价值。
我有一个简单的UICollectionViewController,它是一个带有页眉和页脚固定到可见边界的部分。当我单击页脚中的textField时,页脚会自动在键盘上方进行动画处理,并且collectionView会滚动显示原本会被键盘隐藏的单元格,如您所料。但是,当我单击键盘外部的一个,并通过调用self.view.endEditing(true)
将其关闭时,除非在底部附近滚动collectionView,否则页脚和collectionView不会做出反应。如果collectionView在底部附近滚动,则页脚和collectionView将按预期进行动画处理。
如何每次都强制页脚和collectionView正确设置动画?
在下面的图像中,标题是橙色,页脚是绿色,有10个单元格交替红色和蓝色。
实际行为(当键盘解散时未在collectionView底部附近滚动时发生)
期望的行为(当您在键盘解散时在collectionView的底部或附近滚动时发生)
我知道当键盘出现并消失时,有一些方法可以通过Notifications实现这一点,但我更愿意只使用默认的UICollectionViewController行为。我缺少一些配置或设置吗?
代码:新的单一视图应用程序。删除StoryBoard和ViewController.swift。从info plist文件中删除主Storyboard条目。
AppDelegate.swift
import UIKit
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
window = UIWindow(frame: UIScreen.main.bounds)
window?.makeKeyAndVisible()
window?.rootViewController = CollectionViewController.init()
return true
}
}
CollectionViewController.swift
import UIKit
private let reuseIdentifier = "Cell"
private let collectionViewHeaderFooterReuseIdentifier = "MyHeaderFooterClass"
class CollectionViewController: UICollectionViewController {
init() {
let collectionViewFlowLayout = UICollectionViewFlowLayout.init()
collectionViewFlowLayout.sectionHeadersPinToVisibleBounds = true
collectionViewFlowLayout.sectionFootersPinToVisibleBounds = true
super.init(collectionViewLayout: collectionViewFlowLayout)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
}
override func viewDidLoad() {
super.viewDidLoad()
// Register cell classes
self.collectionView?.register(UICollectionViewCell.self, forCellWithReuseIdentifier: reuseIdentifier)
self.collectionView?.register(MyHeaderFooterClass.self, forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: collectionViewHeaderFooterReuseIdentifier)
self.collectionView?.register(MyHeaderFooterClass.self, forSupplementaryViewOfKind: UICollectionView.elementKindSectionFooter, withReuseIdentifier: collectionViewHeaderFooterReuseIdentifier)
self.collectionView?.backgroundColor = UIColor.white
self.collectionView?.dataSource = self
self.collectionView?.delegate = self
}
}
// MARK: UICollectionViewDelegate
extension CollectionViewController {
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
DispatchQueue.main.async {
self.view.endEditing(true)
self.collectionViewLayout.invalidateLayout()
self.collectionView?.layoutIfNeeded()
}
}
}
// MARK: - UICollectionViewDataSource
extension CollectionViewController {
override func numberOfSections(in collectionView: UICollectionView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of items
return 10
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath)
switch indexPath.row % 2 {
case 0:
cell.backgroundColor = UIColor.red
case 1:
cell.backgroundColor = UIColor.blue
default:
cell.backgroundColor = UIColor.gray
}
return cell
}
override func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
let view = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: collectionViewHeaderFooterReuseIdentifier, for: indexPath)
if kind == UICollectionView.elementKindSectionHeader {
view.backgroundColor = UIColor.orange
}
else { //footer
view.backgroundColor = UIColor.green
}
return view
}
}
// MARK: - Collection View Flow Layout Delegate
extension CollectionViewController: UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: collectionView.frame.width, height: 100)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
return UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 0
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
return CGSize(width: collectionView.frame.width, height: 100)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForFooterInSection section: Int) -> CGSize {
return CGSize(width: collectionView.frame.width, height: 100)
}
}
MyHeaderFooterClass
import UIKit
class MyHeaderFooterClass: UICollectionReusableView {
let textField: UITextField = {
let view = UITextField.init()
view.placeholder = "enter text here"
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
override init(frame: CGRect) {
super.init(frame: frame)
self.addSubview(textField)
self.setNeedsUpdateConstraints()
}
override func updateConstraints() {
textFieldConstraints()
super.updateConstraints()
}
private func textFieldConstraints() {
NSLayoutConstraint(item: textField, attribute: .top, relatedBy: .equal, toItem: self, attribute: .top, multiplier: 1.0, constant: 0.0).isActive = true
NSLayoutConstraint(item: textField, attribute: .left, relatedBy: .equal, toItem: self, attribute: .left, multiplier: 1.0, constant: 0.0).isActive = true
NSLayoutConstraint(item: textField, attribute: .right, relatedBy: .equal, toItem: self, attribute: .right, multiplier: 1.0, constant: 0.0).isActive = true
NSLayoutConstraint(item: textField, attribute: .bottom, relatedBy: .equal, toItem: self, attribute: .bottom, multiplier: 1.0, constant: 0.0).isActive = true
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
来自文档:
func layoutIfNeeded()
使用此方法可强制视图立即更新其布局。
func invalidateLayout()
此方法使集合视图本身的布局无效并立即返回。
解:
查看您的代码,您已经在更新collectionViewLayout
。因此,您无需再次强制更新collectionView
。因此,只需删除
self.collectionView?.layoutIfNeeded()
单独解决你的问题。
更改您的代码如下:
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
DispatchQueue.main.async {
self.view.endEditing(true)
self.collectionViewLayout.invalidateLayout()
//self.collectionView?.layoutIfNeeded()
}
}
以上是关于在endEditing之后,UICollectionViewController页脚没有正确地重新定位自己的主要内容,如果未能解决你的问题,请参考以下文章
使用 tableviewheader 中的 UITextField 在 self.view.endEditing 上崩溃
在表格视图中使用带有文本字段的 endEditing 时崩溃
resignFirstResponder/endEditing 导致访问错误