web-dev-qa-db-fra.com

Comment désactiver le geste de balayage de UIPageViewController?

Dans mon cas, le parent UIViewController contient UIPageViewController qui contient UINavigationController qui contient UIViewController. Je souhaite ajouter un geste de balayage au dernier contrôleur de vue, mais les balayages sont traités comme s'ils appartenaient au contrôleur de vue de page. J'ai essayé de faire cela à la fois par programme et via xib mais sans résultat.

Donc, si j'ai bien compris, je ne pourrai pas atteindre mon objectif tant que UIPageViewController n'aura pas géré ses gestes. Comment résoudre ce problème?

97
user2159978

La méthode documentée pour empêcher le défilement de la UIPageViewController consiste à ne pas affecter la propriété dataSource. Si vous affectez la source de données, elle passera en mode de navigation «basé sur les gestes», ce que vous essayez d'empêcher. 

Sans source de données, vous fournissez manuellement les contrôleurs de vue lorsque vous souhaitez utiliser la méthode setViewControllers:direction:animated:completion. Cette méthode se déplace entre les contrôleurs de vue à la demande. 

Ce qui précède peut être déduit de la documentation Apple sur UIPageViewController (présentation, deuxième paragraphe):

Pour prendre en charge la navigation par gestes, vous devez fournir vos contrôleurs de vue à l'aide d'un objet de source de données.

210
Jessedc
for (UIScrollView *view in self.pageViewController.view.subviews) {

    if ([view isKindOfClass:[UIScrollView class]]) {

        view.scrollEnabled = NO;
    }
}
75
user2159978

Je traduis la réponse de user2159978 en Swift

func removeSwipeGesture(){
    for view in self.pageViewController!.view.subviews {
        if let subView = view as? UIScrollView {
            subView.scrollEnabled = false
        }
    }
}
44
lee

Implémentation de la solution @ lee (@ user2159978) en tant qu'extension:

extension UIPageViewController {
    var isPagingEnabled: Bool {
        get {
            var isEnabled: Bool = true
            for view in view.subviews {
                if let subView = view as? UIScrollView {
                    isEnabled = subView.isScrollEnabled
                }
            }
            return isEnabled
        }
        set {
            for view in view.subviews {
                if let subView = view as? UIScrollView {
                    subView.isScrollEnabled = newValue
                }
            }
        }
    }
}

Utilisation: (dans UIPageViewController)

self.isPagingEnabled = false
21
LinusGeffarth

Edit: cette réponse fonctionne uniquement pour le style de courbure de page. La réponse de Jessedc est bien meilleure: fonctionne indépendamment du style et repose sur comportement documenté.

UIPageViewController expose son tableau de reconnaissance de gestes que vous pouvez utiliser pour les désactiver:

// myPageViewController is your UIPageViewController instance
for (UIGestureRecognizer *recognizer in myPageViewController.gestureRecognizers) {
    recognizer.enabled = NO;
}
9
Austin

Cela fait un moment que je me bats contre cela et je pense que je devrais publier ma solution suite à la réponse de Jessedc; supprimer la source de données de PageViewController.

J'ai ajouté ceci à ma classe PgeViewController (liée à mon contrôleur de vue de page dans le storyboard, hérite à la fois de UIPageViewController et de UIPageViewControllerDataSource):

static func enable(enable: Bool){
    let appDelegate  = UIApplication.sharedApplication().delegate as! AppDelegate
    let pageViewController = appDelegate.window!.rootViewController as! PgeViewController
    if (enable){
        pageViewController.dataSource = pageViewController
    }else{
        pageViewController.dataSource = nil
    }
}

Ceci peut ensuite être appelé lorsque chaque vue secondaire apparaît (dans ce cas, pour la désactiver); 

override func viewDidAppear(animated: Bool) {
    PgeViewController.enable(false)
}

J'espère que cela aide quelqu'un, ce n'est pas aussi propre que je le voudrais mais je ne me sens pas trop malin, etc.

EDIT: Si quelqu'un veut traduire ceci en Objective-C, veuillez le faire :)

8
Jamie Robinson

Une extension utile de UIPageViewController pour activer et désactiver le balayage.

extension UIPageViewController {

    func enableSwipeGesture() {
        for view in self.view.subviews {
            if let subView = view as? UIScrollView {
                subView.isScrollEnabled = true
            }
        }
    }

    func disableSwipeGesture() {
        for view in self.view.subviews {
            if let subView = view as? UIScrollView {
                subView.isScrollEnabled = false
            }
        }
    }
}
4
jbustamante

Si vous souhaitez que votre UIPageViewController conserve sa capacité de balayage, tout en permettant à vos contrôles de contenu d'utiliser leurs fonctions (balayage à supprimer, etc.), désactivez simplement canCancelContentTouches dans UIPageViewController.

Mettez ceci dans votre UIPageViewController 's viewDidLoad func. (Rapide)

if let myView = view?.subviews.first as? UIScrollView {
    myView.canCancelContentTouches = false
}

La UIPageViewController a une sous-vue générée automatiquement qui gère les gestes. Nous pouvons empêcher ces sous-vues d'annuler les mouvements de contenu. 

De...

Balayez pour supprimer sur une table dans un pageViewController

4
Carter Medlin

Je l'ai résolu comme ça (Swift 4.1) 

if let scrollView = self.view.subviews.filter({$0.isKind(of: UIScrollView.self)}).first as? UIScrollView {
             scrollView.isScrollEnabled = false
}
1
user3739902

Similaire à @ user3568340 answer

Swift 4

private var _enabled = true
    public var enabled:Bool {
        set {
            if _enabled != newValue {
                _enabled = newValue
                if _enabled {
                    dataSource = self
                }
                else{
                    dataSource = nil
                }
            }
        }
        get {
            return _enabled
        }
    }
1
Emmanouil Nicolas

Merci à la réponse de @ user2159978.

Je le rend un peu plus compréhensible.

- (void)disableScroll{
    for (UIView *view in self.pageViewController.view.subviews) {
        if ([view isKindOfClass:[UIScrollView class]]) {
            UIScrollView * aView = (UIScrollView *)view;
            aView.scrollEnabled = NO;
        }
    }
}
0
dengApro

Manière rapide pour @lee answer

extension UIPageViewController {
    var isPagingEnabled: Bool {
        get {
            return scrollView?.isScrollEnabled ?? false
        }
        set {
            scrollView?.isScrollEnabled = newValue
        }
    }

    var scrollView: UIScrollView? {
        return view.subviews.first(where: { $0 is UIScrollView }) as? UIScrollView
    }
}
0
Szymon W

(Swift 4) Vous pouvez supprimer les reconnaissances de geste de votre pageViewController:

pageViewController.view.gestureRecognizers?.forEach({ (gesture) in
            pageViewController.view.removeGestureRecognizer(gesture)
        })

Si vous préférez en extension:

extension UIViewController{
    func removeGestureRecognizers(){
        view.gestureRecognizers?.forEach({ (gesture) in
            view.removeGestureRecognizer(gesture)
        })
    }
}

et pageViewController.removeGestureRecognizers

0
Miguel

Déclarez cela comme ceci:

private var scrollView: UIScrollView? {
    return pageViewController.view.subviews.compactMap { $0 as? UIScrollView }.first
}

Ensuite, utilisez-le comme ceci:

scrollView?.isScrollEnabled = true //false

Traduction de la réponse de @ user2159978 en C #:

foreach (var view in pageViewController.View.Subviews){
   var subView = view as UIScrollView;
   if (subView != null){
     subView.ScrollEnabled = enabled;
   }
}
0
gts