Masquer le clavier lors du défilement UITableView

134

Dans mon application, je veux masquer le clavier lorsque je commence à faire défiler UITableView. Je recherche à ce sujet sur Internet, et la plupart des réponses sont sous-classées UITableView (http://stackoverflow.com/questions/3499810/tapping-a-uiscrollview-to-hide-the-keyboard).

J'ai créé une sous-classe mais cela ne fonctionne pas.

#import <UIKit/UIKit.h>

@protocol MyUITableViewDelegate <NSObject>
@optional
- (void)myUITableViewTouchesBegan;
@end

@interface MyUITableView : UITableView <UITableViewDelegate, UIScrollViewDelegate> {
    id<MyUITableViewDelegate> delegate;
}
@end

fichier .m

#import "MyUITableView.h"

@implementation MyUITableView

- (void)scrollViewDidScroll:(UIScrollView *)scrollView{
    NSLog(@"delegate scrollView"); //this is dont'work
    [super scrollViewDidScroll:scrollView];
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    NSLog(@"delegate myUITableViewTouchesBegan"); // work only here
    [delegate myUITableViewTouchesBegan];
    [super touchesBegan:touches withEvent:event];

}

- (void)dealloc {
...

J'utilise cette classe comme ça. Mais la fonction déléguée myUITableViewTouchesBegan ne fonctionne pas dans ViewController

.h

#import <UIKit/UIKit.h>
#import "MyUITableView.h"

@interface FirstViewController : UIViewController <UITableViewDelegate, UISearchBarDelegate, MyUITableViewDelegate> {
    MyUITableView *myTableView;
    UISearchBar *searchBar; 
}

@property(nonatomic,retain) IBOutlet MyUITableView *myTableView;
...

.m

- (void) myUITableViewTouchesBegan{
    NSLog(@"myUITableViewTouchesBegan");
    [searchBar resignFirstResponder];
}

J'ai quelques problèmes avec cette implémentation:
1) myUITableViewTouchesBegan ne fonctionne pas dans ViewController
2) NSLog de MyUITableView.m - NSLog (@ "delegate myUITableViewTouchesBegan"); ne fonctionne que lorsque je touche la table. Comment ça marche aussi quand je commence à faire défiler?
J'essaye de remplacer scrollViewDidScroll mais le comilateur a dit que MyUITableVIew peut être ne pas répondre sur cette chaîne [super scrollViewDidScroll: scrollView];

olégie
la source

Réponses:

144

Je ne sais pas pourquoi vous devez sous-classer UITableView pour cela.

Dans le contrôleur de vue qui contient le UITableView brut, essayez d'ajouter ceci:

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

la source
418

Voici le moyen le plus propre d'y parvenir dans iOS 7.0 et supérieur:

tableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeOnDrag;

Ou pour ignorer de manière interactive en touchant:

tableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeInteractive;

Ou dans Swift:

tableView.keyboardDismissMode = .onDrag

Pour ignorer de manière interactive:

tableView.keyboardDismissMode = .interactive
Pei
la source
21
Cet attribut peut bien sûr également être défini dans l'inspecteur d'attributs pour ceux qui utilisent des pointes et des storyboards.
JuJoDi
1
Mec, j'ai complètement manqué cela comme une mise à jour, j'utilisais toujours une méthode à l'ancienne avec un protocole qui défilait ... Merci mon homme!
Tomas Sykora
3
Pour ceux qui oublient, vous devez toujours faire démissionner UITextfield du premier répondant.
skyline75489
1
Je fais du développement iOS depuis 3 ans et je ne savais pas à ce sujet jusqu'à présent ... irréel.
Jacob King
Comment puis-je manquer ce truc, génial!
trappeur
129

Vous pouvez le faire directement dans Interface Builder. Sélectionnez votre UITableViewet ouvrez l'inspecteur d'attributs. Dans la section Affichage de défilement, définissez le champ Clavier sur Ignorer lors du glissement .

entrez la description de l'image ici

Kyle Clegg
la source
Merci, tu viens de me sauver la vie!
Sabobin
41

Juste pour ajouter une mise à jour aux réponses ci-dessus. Le ci-dessous a fonctionné pour moi dans Swift 1.2

tableView.keyboardDismissMode = UIScrollViewKeyboardDismissMode.OnDrag

ou

tableView.keyboardDismissMode = UIScrollViewKeyboardDismissMode.Interactive
Gareth Jones
la source
2

Avec Swift 5

Pour masquer le clavier lors du défilement de TableView et arrêter correctement l'édition, nous devons encore combiner deux types de réponses:

  1. Définissez le mode de suppression du clavier dans IB (comme Kyle l'a expliqué) ou dans le ViewDidLoad()code (comme Pei l'a expliqué) par exemple:
tableView.keyboardDismissMode = .onDrag
  1. Forcer le champ de texte actuel à démissionner en tant que premier répondant (comme dans la réponse de Vasily ). Nous avons juste besoin d'ajouter ce qui suit à notre UITableViewControllerclasse
    override func scrollViewDidScroll(_ scrollView: UIScrollView) {
        if !tableView.isDecelerating {
            view.endEditing(true)
        }
    }
Thierry G.
la source
1

Solution de travail sans écrire une seule ligne de code dans votre contrôleur:

Comme votre question est de gérer le clavier de masquage avec une seule condition (sur le défilement). Mais ici, je recommande une solution pour gérer le champ de texte et le clavier ensemble qui fonctionne comme du charme pour UIViewController, UITableView et UIScrollView. Le fait intéressant est que vous n'avez pas besoin d'écrire une seule ligne de code.

Ici vous allez: TPKeyboardAvoiding - Une solution géniale pour gérer le clavier et le défilement

iDevAmit
la source
0

Tâche

Masquer le clavier par programme lors du défilement de UITableView dans Swift 3

Détails

xCode 8.2.1, swift 3

Solution

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

Échantillon complet

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>

Résultat

entrez la description de l'image ici

Vasily Bodnarchuk
la source
0

Après iOS 7, vous pouvez simplement utiliser la propriété tableview

Swift 3.0+

myTableView.keyboardDismissMode = UIScrollViewKeyboardDismissMode.OnDrag

Objectif c

myTableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeOnDrag;

Pour les versions antérieures, l'implémentation du délégué de vue de défilement pouvait fonctionner.

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