मैं UIPageViewController के स्वाइप जेस्चर को कैसे अक्षम कर सकता हूं?


125

मेरे मामले में माता-पिता UIViewControllerमें वह UIPageViewControllerसम्‍मिलित है UINavigationControllerजिसमें समाहित है UIViewController। मुझे अंतिम दृश्य नियंत्रक में एक स्वाइप जेस्चर जोड़ने की आवश्यकता है, लेकिन स्वाइप को ऐसे हैंडल किया जाता है मानो वे पृष्ठ दृश्य नियंत्रक से संबंधित हों। मैंने यह दोनों प्रोग्रामेटिक रूप से और xib के माध्यम से करने की कोशिश की, लेकिन कोई परिणाम नहीं मिला।

इसलिए जैसा कि मैं समझता हूं कि मैं अपने लक्ष्य को प्राप्त नहीं कर सकता जब तक UIPageViewControllerकि इसके इशारों को नहीं संभालता। इस समस्या को कैसे हल करें?


7
उपयोगpageViewControllerObject.view.userInteractionEnabled = NO;
श्रीकांत

6
गलत है, क्योंकि यह अपनी सभी सामग्री को भी अवरुद्ध करता है। लेकिन मुझे इसके इशारों को केवल ब्लॉक करने की आवश्यकता है
user2159978

आप यह क्यों कर रहे हैं? आप ऐप से क्या व्यवहार चाहते हैं? ऐसा लगता है कि आप वास्तुकला को ओवरकंप्लीकेट कर रहे हैं। क्या आप बता सकते हैं कि आप किस व्यवहार का लक्ष्य बना रहे हैं।
फोगमिस्टर

पृष्ठों में से एक UIPageViewControllerहै UINavigationController। ग्राहक स्वाइप जेस्चर (यदि यह संभव है) पर नेविगेशन नियंत्रक पॉप करना चाहता है, लेकिन पेज व्यू कंट्रोलर हैंडल स्वाइप करता है
user2159978

@ श्रीकांत धन्यवाद, ठीक वैसा ही जो मुझे चाहिए था! जब मैं किसी पृष्ठ परिवर्तन को प्रोग्रामिक रूप से ट्रिगर करता था तो मेरा पृष्ठ दृश्य क्रैश हो रहा था और किसी ने इसे स्वाइप करने के साथ बाधित किया था, इसलिए मुझे हर बार कोड में ट्रिगर होने पर पृष्ठ परिवर्तन ट्रिगर होने पर अस्थायी रूप से अक्षम करना पड़ा ...
Kuba Suder

जवाबों:


262

UIPageViewControllerस्क्रॉल करने से रोकने के लिए प्रलेखित तरीका dataSourceसंपत्ति को निर्दिष्ट नहीं करना है। यदि आप डेटा स्रोत असाइन करते हैं तो यह 'जेस्चर-आधारित' नेविगेशन मोड में चला जाएगा, जिसे आप रोकने की कोशिश कर रहे हैं।

डेटा स्रोत के बिना जब आप setViewControllers:direction:animated:completionविधि के साथ चाहते हैं तो आप मैन्युअल रूप से दृश्य नियंत्रक प्रदान करते हैं और यह मांग पर दृश्य नियंत्रकों के बीच आगे बढ़ेगा।

ऊपर UIPageViewController के Apple के प्रलेखन से घटाया जा सकता है (अवलोकन, दूसरा पैराग्राफ):

इशारा-आधारित नेविगेशन का समर्थन करने के लिए, आपको डेटा स्रोत ऑब्जेक्ट का उपयोग करके अपने दृश्य नियंत्रक प्रदान करना होगा।


1
मैं इस समाधान को भी पसंद करता हूं। आप पुराने डेटा स्रोत को एक चर में सहेज सकते हैं, डेटा स्रोत को शून्य पर सेट कर सकते हैं, और फिर स्क्रॉलिंग को फिर से सक्षम करने के लिए पुराने डेटा स्रोत को पुनर्स्थापित कर सकते हैं। यह सब साफ नहीं है, लेकिन स्क्रॉल दृश्य को खोजने के लिए अंतर्निहित दृश्य पदानुक्रम को ट्रेस करने से बहुत बेहतर है।
मैट आर

3
डेटा स्रोत को अक्षम करने से पाठ क्षेत्र के साक्षात्कारों के लिए कीबोर्ड सूचनाओं के जवाब में ऐसा करने में समस्या होती है। UIScrollView को खोजने के लिए दृश्य के साक्षात्कार में परिवर्तन अधिक विश्वसनीय प्रतीत होता है।
AR Younce

9
क्या यह स्क्रीन के नीचे डॉट्स को नहीं हटाता है? और अगर आपके पास कोई स्वाइपिंग नहीं है और कोई डॉट्स नहीं है, तो PageViewController का उपयोग करने में बहुत अधिक बिंदु नहीं है। मैं अनुमान लगा रहा हूं कि पूछने वाला डॉट्स को बनाए रखना चाहता है।
लियो फ्लैहर्टी

इससे मुझे उस समस्या को हल करने में मदद मिली जब पृष्ठों को अतुल्यकालिक रूप से लोड किया जाता है और उपयोगकर्ता एक स्वाइप जेस्चर बनाता है। ब्रावो :)
Javock

1
ए। आर Younce सही है। यदि आप कीबोर्ड नोटिफिकेशन के जवाब में PageViewController के डेटा स्रोत को अक्षम कर रहे हैं (यानी: आप उपयोगकर्ता को क्षैतिज रूप से स्क्रॉल करने के लिए नहीं चाहते हैं कि कीबोर्ड कब है) तो जब आप PageViewController के डेटा स्रोत से बाहर निकलते हैं, तो आपका कीबोर्ड तुरंत गायब हो जाएगा।
माइक्रोगुयेन

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

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

        view.scrollEnabled = NO;
    }
}

5
यह एक पृष्ठ नियंत्रण रखता है, जो अच्छा है।
मार्कस एडम्स

1
यह एक महान दृष्टिकोण है क्योंकि यह पृष्ठ नियंत्रण (छोटे डॉट्स) रखता है। पृष्ठ को मैन्युअल रूप से बदलते समय आप उन्हें अपडेट करना चाहेंगे। मैंने इस उत्तर का उपयोग इस stackoverflow.com/a/28356383/1071899
सिमोन बोघ के लिए किया

1
क्यों नहींfor (UIView *view in self.pageViewController.view.subviews) {
dengApro

कृपया ध्यान दें कि उपयोगकर्ता अभी भी बाएँ और दाएँ आधे में पृष्ठ नियंत्रण टैप करके पृष्ठों के बीच नेविगेट कर पाएंगे।
मास्टर कार्ड

57

मैं के जवाब का अनुवाद user2159978 को स्विफ्ट 5.1

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

30

विस्तार के रूप में @ lee's (@ user2159978) समाधान लागू करना:

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
                }
            }
        }
    }
}

उपयोग: (में UIPageViewController)

self.isPagingEnabled = false

अधिक सुरुचिपूर्ण पाने के लिए, आप इसे जोड़ सकते हैं: var scrollView: UIScrollView? { for view in view.subviews { if let subView = view as? UIScrollView { return subView } } return nil }
वैगनर बिक्री

यहां प्राप्त करने वाला केवल अंतिम उप-वर्ग की सक्षम स्थिति देता है।
एंड्रयू डंकन

8

मैं अब थोड़ी देर के लिए यह लड़ाई कर रहा हूं और सोचा कि मुझे अपना समाधान पोस्ट करना चाहिए, जेसडेक के जवाब से; PageViewController के डेटा स्रोत को निकाल रहा है।

मैंने इसे अपने PgeViewController क्लास में जोड़ा (स्टोरीबोर्ड में मेरे पृष्ठ दृश्य नियंत्रक से लिंक किया गया, दोनों को विरासत में मिला UIPageViewControllerऔर 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
    }
}

इसे तब कहा जा सकता है जब प्रत्येक उप दृश्य प्रकट होता है (इस मामले में इसे निष्क्रिय करने के लिए);

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

मुझे आशा है कि यह किसी को बाहर निकालने में मदद करता है, यह उतना साफ नहीं है जितना कि मैं इसे पसंद करूंगा लेकिन यह बहुत अधिक हैकई आदि महसूस नहीं करता है।

संपादित करें: यदि कोई इसे उद्देश्य-सी में अनुवाद करना चाहता है तो कृपया :)


8

संपादित करें : यह उत्तर केवल पृष्ठ कर्ल शैली के लिए काम करता है। जेसडेक का जवाब कहीं बेहतर है: शैली की परवाह किए बिना काम करता है और प्रलेखित व्यवहार पर निर्भर करता है

UIPageViewController इशारा पहचानने वालों के अपने सरणी को उजागर करता है, जिसका उपयोग आप उन्हें अक्षम करने के लिए कर सकते हैं:

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

8
क्या आपने अपने कोड का परीक्षण किया है? myPageViewController.gestureRecognizers हमेशा खाली होता है
user2159978

11
ऐसा लगता है कि आपका समाधान पृष्ठ कर्ल शैली के लिए काम करता है, लेकिन मेरे ऐप में मैं स्क्रॉल दृश्य शैली का उपयोग करता हूं
user2159978

8
क्षैतिज स्क्रॉलिंग के लिए काम नहीं कर रहा है। लौटाया गया मान हमेशा एक खाली सरणी है।
खान गुयेन

क्या आप लोग इसे स्क्रॉल शैली के लिए समझ रहे हैं?
एसकर्राउथ

4

यदि आप चाहते हैं कि आप UIPageViewControllerइसे स्वाइप करने की क्षमता बनाए रखें, तो आपकी सामग्री नियंत्रण को उनकी सुविधाओं का उपयोग करने की अनुमति देती है (स्वाइप को हटाने के लिए, आदि), बस बंद कर दें canCancelContentTouchesUIPageViewController

अपने में इस रखो UIPageViewControllerके viewDidLoadसमारोह। (स्विफ्ट)

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

UIPageViewControllerएक स्वत: जनरेट subview कि इशारों संभालती है। हम इन साक्षात्कारों को सामग्री इशारों को रद्द करने से रोक सकते हैं।

से ...

किसी पृष्ठ दृश्य के अंदर जो तालिका दृश्य पर हटाने के लिए स्वाइप करें


धन्यवाद कार्टर। मैंने आपके समाधान की कोशिश की है। हालाँकि, अभी भी कई बार पेज व्यू कॉन्ट्रोलर ओवर-टेक हो रहे हैं, जो कि स्वाइप एक्शन को चाइल्ड टेबल व्यू से दूर रखते हैं। मैं यह कैसे सुनिश्चित कर सकता हूं कि जब उपयोगकर्ता चाइल्ड टेबल व्यू पर स्वाइप करता है, तो टेबल व्यू को हमेशा पहले इशारे पर लाने के लिए प्राथमिकता दी जाती है?
डेविड लियू

3

UIPageViewControllerस्वाइप को सक्षम और अक्षम करने का एक उपयोगी विस्तार ।

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
            }
        }
    }
}

3

मैंने इसे इस तरह हल किया (स्विफ्ट 4.1)

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

3

@ उत्तर के लिए स्विफ्टी का तरीका

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

@ User3568340 उत्तर के समान

स्विफ्ट 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
        }
    }

0

@ User2159978 के जवाब के लिए धन्यवाद।

मैं इसे थोड़ा और समझने योग्य बनाता हूं।

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

0

जो उत्तर मुझे मिले, वे मेरे लिए बहुत भ्रामक या अधूरे हैं, इसलिए यहाँ एक पूर्ण और विन्यास योग्य समाधान है:

चरण 1:

अपने प्रत्येक पीवीसी तत्वों को यह बताने की जिम्मेदारी दें कि बाएं और दाएं स्क्रॉल सक्षम हैं या नहीं।

protocol PageViewControllerElement: class {
    var isLeftScrollEnabled: Bool { get }
    var isRightScrollEnabled: Bool { get }
}
extension PageViewControllerElement {
    // scroll is enabled in both directions by default
    var isLeftScrollEnabled: Bool {
        get {
            return true
        }
    }

    var isRightScrollEnabled: Bool {
        get {
            return true
        }
    }
}

आपके प्रत्येक पीवीसी दृश्य नियंत्रक को उपरोक्त प्रोटोकॉल को लागू करना चाहिए।

चरण 2:

अपने पीवीसी नियंत्रकों में, यदि आवश्यक हो तो स्क्रॉल को अक्षम करें:

extension SomeViewController: PageViewControllerElement {
    var isRightScrollEnabled: Bool {
        get {
            return false
        }
    }
}

class SomeViewController: UIViewController {
    // ...    
}

चरण 3:

अपने पीवीसी पर प्रभावी स्क्रॉल लॉक विधियाँ जोड़ें:

class PVC: UIPageViewController, UIPageViewDelegate {
    private var isLeftScrollEnabled = true
    private var isRightScrollEnabled = true
    // ...

    override func viewDidLoad() {
        super.viewDidLoad()
        // ...
        self.delegate = self
        self.scrollView?.delegate = self
    }
} 

extension PVC: UIScrollViewDelegate {
    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        print("contentOffset = \(scrollView.contentOffset.x)")

        if !self.isLeftScrollEnabled {
            disableLeftScroll(scrollView)
        }
        if !self.isRightScrollEnabled {
            disableRightScroll(scrollView)
        }
    }

    private func disableLeftScroll(_ scrollView: UIScrollView) {
        let screenWidth = UIScreen.main.bounds.width
        if scrollView.contentOffset.x < screenWidth {
            scrollView.setContentOffset(CGPoint(x: screenWidth, y: 0), animated: false)
        }
    }

    private func disableRightScroll(_ scrollView: UIScrollView) {
        let screenWidth = UIScreen.main.bounds.width
        if scrollView.contentOffset.x > screenWidth {
            scrollView.setContentOffset(CGPoint(x: screenWidth, y: 0), animated: false)
        }
    }
}

extension UIPageViewController {
    var scrollView: UIScrollView? {
        return view.subviews.filter { $0 is UIScrollView }.first as? UIScrollView
    }
}

चरण 4:

नई स्क्रीन पर पहुंचने पर स्क्रॉल संबंधी विशेषताओं को अपडेट करें (यदि आप कुछ स्क्रीन पर मैन्युअल रूप से संक्रमण करते हैं तो enableScroll विधि को कॉल करना न भूलें):

func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {
    let pageContentViewController = pageViewController.viewControllers![0]
    // ...

    self.enableScroll(for: pageContentViewController)
}

private func enableScroll(for viewController: UIViewController) {
    guard let viewController = viewController as? PageViewControllerElement else {
        self.isLeftScrollEnabled = true
        self.isRightScrollEnabled = true
        return
    }

    self.isLeftScrollEnabled = viewController.isLeftScrollEnabled
    self.isRightScrollEnabled = viewController.isRightScrollEnabled

    if !self.isLeftScrollEnabled {
        print("Left Scroll Disabled")
    }
    if !self.isRightScrollEnabled {
        print("Right Scroll Disabled")
    }
}

0

यहां दिए गए अधिकांश उत्तरों की तुलना में बहुत सरल दृष्टिकोण है, जो कि डेटाबैक और डेटा स्रोत कॉलबैक nilमें वापस आना है।viewControllerBeforeviewControllerAfter

इस प्रकार से अक्षम iOS पर स्क्रॉल इशारा 11+ उपकरणों, जबकि उपयोग करने के लिए संभावना रखने dataSourceजैसे (बातों के लिए presentationIndex/presentationCount लिए)

यह नेविगेशन को भी निष्क्रिय कर देता है। pageControl(नीचे में डॉट्स)

extension MyPageViewController: UIPageViewControllerDataSource {
    func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
        return nil
    }
    
    func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
        return nil
    }
}


-1

@ User2159978 की C # पर प्रतिक्रिया का अनुवाद:

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

-1

(स्विफ्ट 4) आप अपने पेज के इशारों को हटा सकते हैं।

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

यदि आप विस्तार में पसंद करते हैं:

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

तथा pageViewController.removeGestureRecognizers



-1

UIPageViewControllerमेरे लिए कोई काम नहीं किया है, क्योंकि मैं अपने पेज कंट्रोलरक्लास में किसी भी स्क्रॉल दृश्य को नहीं पा सकता हूँ, मेरे लिए कोई काम नहीं करने के लिए स्क्रॉलडाउन खोजने के लिए साक्षात्कार की गणना करना । इसलिए मैंने जो करने के बारे में सोचा था वह इशारा पहचानने वालों को अक्षम करना है, लेकिन आवश्यक लोगों को अक्षम नहीं करने के लिए पर्याप्त सावधान।

इसलिए मैं इसके साथ आया:

if let panGesture = self.gestureRecognizers.filter({$0.isKind(of: UIPanGestureRecognizer.self)}).first           
    panGesture.isEnabled = false        
}

कि अंदर रखो viewDidLoad()और तुम सब सेट कर रहे हैं!


-1
 override func viewDidLayoutSubviews() {
    for View in self.view.subviews{
        if View.isKind(of: UIScrollView.self){
            let ScrollV = View as! UIScrollView
            ScrollV.isScrollEnabled = false
        }

    }
}

इसे अपने पेजव्यूकंट्रोलर वर्ग में जोड़ें। 100% काम कर रहा है


कृपया टिप्पणी करें कि आप इस कोड का सामना किस मुद्दे पर पूरी तरह से कर रहे हैं: /
ap00724

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.