programing

UIPageView 컨트롤러의 스와이프 제스처를 비활성화하려면 어떻게 해야 합니까?

cafebook 2023. 6. 27. 23:39
반응형

UIPageView 컨트롤러의 스와이프 제스처를 비활성화하려면 어떻게 해야 합니까?

부모님 나의경부님모우님▁in.UIViewController를 포함합니다.UIPageViewController에는 는것하함포가 들어 있습니다.UINavigationController에는 는것하함포가 들어 있습니다.UIViewController마지막 보기 컨트롤러에 스와이프 제스처를 추가해야 하는데 스와이프는 페이지 보기 컨트롤러에 속한 것처럼 처리됩니다.프로그래밍과 xib를 통해 모두 시도했지만 결과가 없었습니다.

그래서 제가 알기로는 제 목표를 달성할 수 없습니다.UIPageViewController제스처를 처리합니다.이 문제를 어떻게 해결합니까?

은 다음과 .UIPageViewController스크롤링에서 지정하지 않는 것입니다.dataSource 하면 ' 기반'하고자 합니다.데이터 소스를 할당하면 해당 데이터 소스가 '동작 기반' 탐색 모드로 전환되며, 이는 사용자가 방지하려는 것입니다.

경우 으로 뷰 합니다.setViewControllers:direction:animated:completion요청 시 뷰 컨트롤러 간에 이동합니다.

내용은 Apple의 UIPageView 컨트롤러 설명서(개요, 두 번째 단락)에서 추론할 수 있습니다.

제스처 기반 탐색을 지원하려면 데이터 원본 개체를 사용하여 뷰 컨트롤러를 제공해야 합니다.

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

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

        view.scrollEnabled = NO;
    }
}

사용자 2159978의 답변을 Swift 5.1로 번역합니다.

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

확장으로 @lee's (@user2159978's) 솔루션 구현:

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

( 사량용: (in)UIPageViewController)

self.isPagingEnabled = false

저는 한동안 이 문제를 해결하기 위해 노력했지만 Jessec의 답변에 따라 PageViewController의 데이터 소스를 제거하는 솔루션을 게시해야겠다고 생각했습니다.

되어 있으며, "PgeViewController" ("PgeViewController", "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)
}

이것이 누군가에게 도움이 되길 바랍니다, 제가 원하는 만큼 깨끗하지는 않지만 너무 촌스럽게 느껴지지는 않습니다.

편집: 누군가 이것을 목표-C로 번역하고 싶다면 그렇게 하세요 :)

편집: 이 답변은 페이지 컬 스타일에만 사용할 수 있습니다.Jessec의 대답은 훨씬 낫습니다: 스타일에 상관없이 작동하고 문서화된 행동에 의존합니다.

UIPageViewController에서는 제스처 인식기 배열을 표시하며, 이를 사용하여 제스처 인식기를 비활성화할 수 있습니다.

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

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

당신이 원한다면 당신의UIPageViewController내용 컨트롤이 해당 기능을 사용할 수 있도록 허용하는 동시에 스와이프 기능을 유지하려면(삭제하려면 스와이프 등) 그냥 해제합니다.canCancelContentTouches에 시대에UIPageViewController.

이것을 당신의 안에 넣으세요.UIPageViewControllerviewDidLoad ( func. (빠른)

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

UIPageViewController제스처를 처리하는 자동 생성 하위 보기가 있습니다.이러한 하위 보기가 내용 제스처를 취소하는 것을 방지할 수 있습니다.

출처...

테이블에서 삭제하려면 문지르기페이지 내의 보기컨트롤러 보기

@lee 답변을 위한 빠른 방법.

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.1)

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

신속한 해결책이 여기 있습니다.

extension UIPageViewController {
    var isScrollEnabled: Bool {
        set {
            (self.view.subviews.first(where: { $0 is UIScrollView }) as? UIScrollView)?.isScrollEnabled = newValue
        }
        get {
            return (self.view.subviews.first(where: { $0 is UIScrollView }) as? UIScrollView)?.isScrollEnabled ?? true
        }
    }
}

pageViewController.view.isUserInteractionEnabled = false

이렇게 하면 페이지와의 모든 상호 작용이 비활성화됩니다.내용과 상호 작용할 수 있도록 사용자가 필요한 경우 이 방법은 사용자에게 적합하지 않습니다.

제시하는 보다 훨씬 여서대부답제것안훨보간접있씬습다것즉니다입니는근기오되이돌법아단한다는하의.nil에 시대에viewControllerBefore그리고.viewControllerAfterdataSource 파일입니다.

기기에서 수에, iOS 11+ 기기에서 스크롤 제스처를 사용할 수 있는 가능성을 유지합니다.dataSource((예를들어)들)와 같은 presentationIndex/presentationCount페이지 표시기에 사용됨)

또한 을 통한 탐색을 비활성화합니다.pageControl(하단의 점)은 iOS 11-13용입니다.에서는 UIA 를 할 수 .OS 14에서는 UIA 모양 프록시를 사용하여 하단 도트 탐색을 비활성화할 수 있습니다.

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

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

C#에 대한 @user2159978의 응답 번역:

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

@user2159978님의 답변에 감사드립니다.

저는 그것을 좀 더 이해하기 쉽게 만듭니다.

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

(Swift 4) 페이지의 제스처 인식자를 제거할 수 있습니다. ViewController:

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

확장을 원하는 경우:

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

그리고.pageViewController.removeGestureRecognizers

다음과 같이 선언합니다.

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

그런 다음 다음과 같이 사용합니다.

scrollView?.isScrollEnabled = true //false

제가 찾은 답변은 매우 혼란스럽거나 불완전해 보이므로 다음은 완벽하고 구성 가능한 솔루션입니다.

1단계:

각 PVC 요소에 왼쪽 및 오른쪽 스크롤이 활성화되었는지 여부를 판단할 책임을 부여합니다.

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

각 PVC 보기 컨트롤러는 위의 프로토콜을 구현해야 합니다.

2단계:

PVC 컨트롤러에서 필요한 경우 스크롤을 비활성화합니다.

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

class SomeViewController: UIViewController {
    // ...    
}

3단계:

PVC에 효과적인 스크롤 잠금 방법을 추가합니다.

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

반환 시 보다 효율적인 방법은 View didload에서 다음 방법을 호출합니다(Swift 5).

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

다을구할수다있니를 할 수 .UIPageViewControllerDataSource return nil이전 ViewController 및 nextViewController 메서드에 적용됩니다.이렇게 하면 다음을 방지할 수 있습니다.UIPageViewController다음 페이지 또는 이전 페이지로 이동할 수 있습니다.

    fileprivate func canSwipeToNextViewController() -> Bool {
        guard
            currentIndex < controllers.count,
            let controller = controllers[currentIndex] as? OnboardingBaseViewController,
            controller.canSwipeToNextScreen
        else {
            return false
        }

        return true
    }
}

// MARK: - UIPageViewControllerDataSource

extension ViewController: UIPageViewControllerDataSource {
    func presentationCount(for pageViewController: UIPageViewController) -> Int {
        controllers.count
    }

    func presentationIndex(for pageViewController: UIPageViewController) -> Int {
        currentIndex
    }

    func pageViewController(
        _ pageViewController: UIPageViewController,
        viewControllerBefore viewController: UIViewController
    ) -> UIViewController? {
        if let index = controllers.firstIndex(of: viewController) {
            if index > 0 {
                currentIndex -= 1
                return controllers[index - 1]
            } else {
                // Return nil to prevent swiping to the previous page
                return nil
            }
        }

        return nil
    }

    func pageViewController(
        _ pageViewController: UIPageViewController,
        viewControllerAfter viewController: UIViewController
    ) -> UIViewController? {
        if let index = controllers.firstIndex(of: viewController) {
            if index < controllers.count - 1,
               canSwipeToNextViewController() {
                currentIndex += 1
                return controllers[index + 1]
            } else {
                // Return nil to prevent swiping to the next page
                return nil
            }
        }

        return nil
    }
}

설정하는 것을 기억하십시오.dataSource의 재산.UIPageViewController를 구현하는 보기 컨트롤러에UIPageViewControllerDataSource의전

그게 도움이 되길 바랍니다.

의 스크롤 보기를 찾기 위해 하위 보기 열거UIPageViewController페이지 컨트롤러 하위 클래스에서 scrollView를 찾을 수 없기 때문에 작동하지 않았습니다.그래서 제가 생각한 것은 제스처 인식기를 비활성화하는 것입니다. 하지만 필요한 것을 비활성화하지 않도록 충분히 주의해야 합니다.

그래서 저는 이렇게 생각해냈습니다.

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

을 것을안 넣요으세 안에 .viewDidLoad()준비가 다 됐습니다!

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

    }
}

페이지뷰 컨트롤러 클래스에 추가합니다.100% 작동하는

이 컨트롤 속성을 UIPageViewController 하위 클래스에 추가하기만 하면 됩니다.

var isScrollEnabled = true {
    didSet {
        for case let scrollView as UIScrollView in view.subviews {
            scrollView.isScrollEnabled = isScrollEnabled
        }
    }
}

언급URL : https://stackoverflow.com/questions/22098493/how-do-i-disable-the-swipe-gesture-of-uipageviewcontroller

반응형