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?
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.
for (UIScrollView *view in self.pageViewController.view.subviews) {
if ([view isKindOfClass:[UIScrollView class]]) {
view.scrollEnabled = NO;
}
}
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
}
}
}
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
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;
}
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 :)
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
}
}
}
}
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
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
}
Similaire à @ user3568340 answer
private var _enabled = true
public var enabled:Bool {
set {
if _enabled != newValue {
_enabled = newValue
if _enabled {
dataSource = self
}
else{
dataSource = nil
}
}
}
get {
return _enabled
}
}
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;
}
}
}
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
}
}
(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
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;
}
}