olegi
olegi

Reputation: 2061

Hide keyboard when scroll UITableView

In my app I want to hide keyboard when I start scrolling any UITableView or scroll view.

Upvotes: 146

Views: 78151

Answers (8)

Kyle Clegg
Kyle Clegg

Reputation: 39470

You can do this right in Interface Builder. Select your UITableView and open the Attributes Inspector. In the Scroll View section set the Keyboard field to Dismiss on Drag.

enter image description here

Notes for 2024,

  • this works perfectly for both any scroll view and any table view

  • there is absolutely no need whatsoever to override anything. any answers which mention overriding something, are simply, completely wrong

  • the feature is entirely built in to iOS, and as of recent versions works perfectly. simply turn it on. there is nothing else to do.

  • you can do it on storyboard as in the image, or in code it is just tableView.keyboardDismissMode = .onDrag. it is exactly the same thing, code or storyboard.

Upvotes: 137

Thierry G.
Thierry G.

Reputation: 291

With Swift 5

To hide the keyboard when scrolling the TableView and stop editing properly, we still need to combine two types of answers:

  1. Set the keyboard dismiss mode in IB (as Kyle explained) or in ViewDidLoad() code (as Pei explained) for instance:
tableView.keyboardDismissMode = .onDrag
  1. Force the current textfield to resign as first responder (as in Vasily's answer). We just need to add the following to our UITableViewController class
    override func scrollViewDidScroll(_ scrollView: UIScrollView) {
        if !tableView.isDecelerating {
            view.endEditing(true)
        }
    }

Upvotes: 10

Pei
Pei

Reputation: 11643

Here is the cleanest way to achieve this in iOS 7.0 and above:

tableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeOnDrag;

Or to dismiss interactively when touching:

tableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeInteractive;

Or in Swift:

tableView.keyboardDismissMode = .onDrag

To dismiss interactively:

tableView.keyboardDismissMode = .interactive

Upvotes: 468

vrat2801
vrat2801

Reputation: 548

After iOS 7, you can simple use the tableview property

Swift 3.0+

myTableView.keyboardDismissMode = UIScrollViewKeyboardDismissMode.OnDrag

ObjectiveC

myTableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeOnDrag;

For earlier versions, implementing the scroll view delegate could work.

func scrollViewDidScroll(_ scrollView: UIScrollView) {
        view.endEditing(true)
}

Upvotes: 1

iDevAmit
iDevAmit

Reputation: 1578

Working solution without writing single line of code in your Controller:

As your question is to handle the hide keyboard with one condition only (on scroll). But here I am recommending one solution to handle textfield and keyboard together which works like charm for UIViewController, UITableView and UIScrollView. The interesting fact is that You do not need to write any single line of code.

Here you go: TPKeyboardAvoiding - An awesome solution to handle keyboard and scroll

Upvotes: 0

Vasily  Bodnarchuk
Vasily Bodnarchuk

Reputation: 25294

Task

Hide keyboard programmatically when scroll UITableView in Swift 3

Details

xCode 8.2.1, swift 3

Solution

func scrollViewDidScroll(_ scrollView: UIScrollView) {
    if !tableView.isDecelerating {
        view.endEditing(true)
    }
}

Full Sample

ViewController

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var tableView: UITableView!
    @IBOutlet weak var searchBar: UISearchBar!


    override func viewDidLoad() {
        super.viewDidLoad()
        tableView.dataSource = self
        tableView.delegate = self
    }
}

// MARK: - UITableViewDataSource

extension ViewController: UITableViewDataSource {

    func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 100
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell =  UITableViewCell(style: .subtitle, reuseIdentifier: nil)
        cell.textLabel?.text = "Title"
        cell.detailTextLabel?.text = "\(indexPath)"
        return cell
    }
}

// MARK: - UITableViewDelegate

extension ViewController: UITableViewDelegate {

    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        if !tableView.isDecelerating {
            view.endEditing(true)
        }
    }
}

StoryBoard

<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="11762" systemVersion="16D32" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
    <device id="retina4_7" orientation="portrait">
        <adaptation id="fullscreen"/>
    </device>
    <dependencies>
        <deployment identifier="iOS"/>
        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11757"/>
        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
    </dependencies>
    <scenes>
        <!--View Controller-->
        <scene sceneID="tne-QT-ifu">
            <objects>
                <viewController id="BYZ-38-t0r" customClass="ViewController" customModule="stackoverflow_4399357" customModuleProvider="target" sceneMemberID="viewController">
                    <layoutGuides>
                        <viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/>
                        <viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
                    </layoutGuides>
                    <view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
                        <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                        <subviews>
                            <searchBar contentMode="redraw" translatesAutoresizingMaskIntoConstraints="NO" id="wU1-dV-ueB">
                                <rect key="frame" x="0.0" y="20" width="375" height="44"/>
                                <textInputTraits key="textInputTraits"/>
                            </searchBar>
                            <tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" keyboardDismissMode="interactive" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="44" sectionHeaderHeight="28" sectionFooterHeight="28" translatesAutoresizingMaskIntoConstraints="NO" id="L52-4c-UtT">
                                <rect key="frame" x="0.0" y="64" width="375" height="603"/>
                                <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
                            </tableView>
                        </subviews>
                        <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                        <constraints>
                            <constraint firstItem="wU1-dV-ueB" firstAttribute="bottom" secondItem="L52-4c-UtT" secondAttribute="top" id="0WF-07-qY1"/>
                            <constraint firstAttribute="trailing" secondItem="wU1-dV-ueB" secondAttribute="trailing" id="3Mj-h0-IvO"/>
                            <constraint firstItem="wU1-dV-ueB" firstAttribute="leading" secondItem="L52-4c-UtT" secondAttribute="leading" id="8W5-9j-2Rg"/>
                            <constraint firstItem="wU1-dV-ueB" firstAttribute="trailing" secondItem="L52-4c-UtT" secondAttribute="trailing" id="crK-dR-UYf"/>
                            <constraint firstItem="wU1-dV-ueB" firstAttribute="leading" secondItem="8bC-Xf-vdC" secondAttribute="leading" id="mPe-bp-Dxw"/>
                            <constraint firstItem="L52-4c-UtT" firstAttribute="bottom" secondItem="wfy-db-euE" secondAttribute="top" id="oIo-DI-vLh"/>
                            <constraint firstItem="wU1-dV-ueB" firstAttribute="top" secondItem="y3c-jy-aDJ" secondAttribute="bottom" id="tVC-UR-PA4"/>
                        </constraints>
                    </view>
                    <connections>
                        <outlet property="searchBar" destination="wU1-dV-ueB" id="xJf-bq-4t9"/>
                        <outlet property="tableView" destination="L52-4c-UtT" id="F0T-yb-h5r"/>
                    </connections>
                </viewController>
                <placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
            </objects>
            <point key="canvasLocation" x="-79.200000000000003" y="137.18140929535232"/>
        </scene>
    </scenes>
</document>

Result

enter image description here

Upvotes: 0

Gareth Jones
Gareth Jones

Reputation: 1810

Just to add an update to the answers above. The below worked for me in Swift 1.2

tableView.keyboardDismissMode = UIScrollViewKeyboardDismissMode.OnDrag

or

tableView.keyboardDismissMode = UIScrollViewKeyboardDismissMode.Interactive

Upvotes: 44

user467105
user467105

Reputation:

Not sure why you need to subclass UITableView for this.

In the view controller that contains the plain UITableView, try adding this:

- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
    [searchBar resignFirstResponder];
}

Upvotes: 149

Related Questions