Bepa1012
Bepa1012

Reputation: 23

Swift: Jump to next Textfield in a CollectionView

Im trying to jump from one Textfield in a Cell, to the TextField in the next Cell of a CollectionView, by hitting the enter button, but I can't get it to work.

I have assigned an individual Tag to all the Textfields when the cells get create, by giving every Textfield the corresponding indexPath as Tag:

// make a cell for each cell index path
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

    // get a reference to our storyboard cell
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath as IndexPath) as! MyCollectionViewCell

    // Use the outlet in our custom class to get a reference to the UILabel in the cell
    cell.myLabel.text = self.items[indexPath.item]
    cell.myTextField.tag = indexPath.row
    cell.backgroundColor = UIColor(red:0.94, green:0.94, blue:0.94, alpha:1.0) // make cell more visible in our example project

    // Change shape of cells
    cell.layer.cornerRadius = 8

    return cell
}

Now my intention was, to use the code below to get to the next Textfield, if there is one:

extension ViewController: UITextFieldDelegate {
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
    // Try to find next responder
    print(textField.tag) // Test if chosen textfield has individual tag
    if let nextField = textField.superview?.viewWithTag(textField.tag + 1) as? UITextField {
        nextField.becomeFirstResponder()
    } else {
        // Not found, so remove keyboard.
        textField.resignFirstResponder()
    }
    // Do not add a line break
    return false
}

}

But whenever I click on the enter button, nextField is always nil, the else case will be executed and the keyboard goes away. My guess is, that nextField looks in the wrong place for other TextFields and thats the reason why it can't find them (There is one Textfield per Cell, but no TextFields in the ViewController directly).

Since Im pretty new to programming in general, I have no clue how to solve this problem.

Upvotes: 1

Views: 1765

Answers (2)

J.Ren
J.Ren

Reputation: 76

if let nextField = textField.superview?.viewWithTag(textField.tag + 1) as? UITextField

In this code textField.superview is current cell.There is no view's tag equal textField.tag + 1.You should get next cell first,then get textFiled. Change your code like this

func textFieldShouldReturn(_ textField: UITextField) -> Bool {
// Try to find next responder 
    print(textField.tag)
// Test if chosen textfield has individual tag
    let nextCell = self.collectionView?.cellForItem(at: IndexPath.init(row: textField.tag + 1, section: 0))
if let nextField = nextCell.viewWithTag(textField.tag + 1) as? UITextField {
    nextField.becomeFirstResponder()
} else {
    // Not found, so remove keyboard.
    textField.resignFirstResponder()
}
    // Do not add a line break
return false
}

Upvotes: 2

rmaddy
rmaddy

Reputation: 318794

You are incorrectly assuming that the collection view is the super view of each text field. This isn't true. The text field's superview is actually the collection view cell's contentView which in turn is some deep down subview of the collection view cell which is ultimately a subview of the collection view.

You also have an issue of trying to move to the next text field when the next text field isn't even visible.

You need to take a different approach. At a high level you need to do the following in your textFieldShouldReturn method:

  1. Determine the index path of the cell for the text field.
  2. Calculate the next index path.
  3. Ensure the cell for the next index path is in view.
  4. Make the text field of the next cell the first responder.

For step 1 you need to convert a point in the text field to a point in the collection view. Then use the collection view method indexPathForItem(at:) to get the index path of the cell for the current text field.

For step 2 it depends on your layout. Simply increment the item. Possibly increment the section. Be sure to check if you are at the last cell.

For step 3, scroll the collection view as needed.

For step 4, use the cellForItem(at:) collection view method passing in the new index path from step 2. This gives you the next cell. Then access its text field and make it the first responder.

Upvotes: 1

Related Questions