Reputation: 621
This isn't my desired effect. This only happens when the collection view is set to horizontal flow layout. I've seen a few other posts regarding this very same issue but none of the provided answers have worked. Has anyone found a solution?
I've provided two screenshots showing a UITextField before the keyboard is triggered and after. As you can see the UITextField along with the entire collection view (which can't be seen) is pushed up along with the keyboard. Usually the keyboard is overlayed having no effect on the views.
Before
After
Update Code provided. The method I used to implement doesn't involve a Storyboard.
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
window = UIWindow()
window?.makeKeyAndVisible()
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .horizontal
let rvc = ViewController(collectionViewLayout: layout)
window?.rootViewController = rvc
return true
}
// .... other boilerplate code provided by Apple when you make a new App
}
ViewController.swift
class ViewController: UICollectionViewController, UICollectionViewDelegateFlowLayout, UITextFieldDelegate {
let homeCellId = "homeCellId"
let worldCellId = "worldCellId"
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = UIColor.white
collectionView?.register(HomeCell.self, forCellWithReuseIdentifier: homeCellId)
collectionView?.register(WorldCell.self, forCellWithReuseIdentifier: worldCellId)
collectionView?.isPagingEnabled = true
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 2
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: view.frame.width, height: view.frame.height)
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
print(indexPath.item)
let identifier: String
if indexPath.item == 0 {
identifier = homeCellId
} else if indexPath.item == 1 {
identifier = worldCellId
}
else {
identifier = homeCellId
}
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: identifier, for: indexPath)
cell.backgroundColor = UIColor.blue
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 0
}
}
MyCell.swift
class MyCell: UICollectionViewCell {
override init(frame: CGRect) {
super.init(frame: frame)
self.setupView()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func setupView() {
}
}
HomeCell.swift
class HomeCell: MyCell {
let weightField: UITextField = UITextField(frame: .zero)
override func setupView() {
super.setupView()
print("HomeCell")
weightField.backgroundColor = UIColor.white
weightField.translatesAutoresizingMaskIntoConstraints = false
weightField.keyboardType = UIKeyboardType.default
self.addSubview(weightField)
weightField.topAnchor.constraint(equalTo: self.topAnchor, constant: 200).isActive = true
weightField.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 50).isActive = true
}
}
WorldCell.swift
// same as HomeCell
class WorldCell: MyCell {
override func setupView() {
super.setupView()
print("worldcell")
}
}
Upvotes: 0
Views: 2337
Reputation: 621
Okay so I've found a solution to this problem. I came across this in a couple of other threads on stackoverflow regarding a similar incident, in one case the Answer had no votes attributed to it and a comment left to the answer said it didn't work..
Though after all this I'm still not crystal clear on why the other implementation causes the collection view to shift up. Though there is some correlation between the window, root view controller and it's subviews along with the keyboard. Why this happens I don't know.
Now on to the code and fix..
The main different between the method in the question above and here is the way the collection view is initialised. I'll only post what I changed because the rest is just the same.
AppDelegate.swift
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
let rvc = ViewController()
window? = UIWindow()
window?.makeKeyAndVisible()
window?.rootViewController = rvc
return true
}
}
The striking difference here is the root view controller is no longer initialised with the Collection View Controller. We use a standard View Controller.
ViewController.swift
class ViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout {
lazy var collView: UICollectionView = {
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .horizontal
let view = UICollectionView(frame: .zero, collectionViewLayout: layout)
view.dataSource = self
view.delegate = self
return view
}()
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = UIColor.darkGray
collView.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "cellId")
collView.register(HomeCell.self, forCellWithReuseIdentifier: "homeCellId")
self.view.addSubview(collView)
collView.backgroundColor = UIColor.blue
collView.translatesAutoresizingMaskIntoConstraints = false
collView.topAnchor.constraint(equalTo: self.view.topAnchor).isActive = true
collView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor).isActive = true
collView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor).isActive = true
collView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor).isActive = true
collView.heightAnchor.constraint(equalTo: self.view.heightAnchor, multiplier: 1)
// Do any additional setup after loading the view, typically from a nib.
}
}
We initialise the View Controller with a collectionview as a subview and apply the same code we would normally to the cells
Upvotes: 1