我正在使用 UIPageViewController 开发像滑块这样的图片库,并且在 UIPageViewController 转换样式模式下遇到了 Scroll 自动插入的问题。

这是我的布局:

  • UIViewControllerUIContainerView(洋红色背景)
  • UIPageViewController 链接到容器(来自 #1)
  • 页面 Controller 中动态创建的 View UIViewController(s) 列表(来自 #2),全宽高 View (1. 橙色,2. 红色,3. 绿色)

  • uiscrollview - 带有滚动过渡样式的 UIPageViewController 自动为 iPhone X 添加安全区域插图-LMLPHP

    它曾经可以正常工作很长时间并且继续与 iOS 11 一起工作,除非它在具有安全区域的 iPhone X 设备上呈现:

    uiscrollview - 带有滚动过渡样式的 UIPageViewController 自动为 iPhone X 添加安全区域插图-LMLPHP

    我检查了很多不同的选项,并能够确认它与页面 Controller 的滚动模式特别相关。如果我切换到 PageCurl 过渡样式 - 它会按预期工作(全高):

    uiscrollview - 带有滚动过渡样式的 UIPageViewController 自动为 iPhone X 添加安全区域插图-LMLPHP

    页面 Controller 没有公开很多选项来控制滚动模式的这种行为,我也无法通过搜索控件树并修改各种 insetsframe 以及 contentSize 相关属性来“破解”它。我可以清楚地看到,一旦创建了 View Controller ,我的滚动 View contentSizeframe34px 比容器 frame
    > view.frame
    {{X=0,Y=0,Width=375,Height=732}}
        Bottom: 732
        Height: 732
        IsEmpty: false
        Left: 0
        Location: {{X=0, Y=0}}
        Right: 375
        Size: {{Width=375, Height=732}}
        Top: 0
        Width: 375
        X: 0
        Y: 0
    
    > scroll.frame
    {{X=-5,Y=0,Width=385,Height=698}}
        Bottom: 698
        Height: 698
        IsEmpty: false
        Left: -5
        Location: {{X=-5, Y=0}}
        Right: 380
        Size: {{Width=385, Height=698}}
        Top: 0
        Width: 385
        X: -5
        Y: 0
    
    > scroll.contentSize
    {{Width=1155, Height=698}}
        Height: 698
        IsEmpty: false
        Width: 1155
    

    我还设置了自动布局约束以链接到 super View 而不是安全区域:

    uiscrollview - 带有滚动过渡样式的 UIPageViewController 自动为 iPhone X 添加安全区域插图-LMLPHP

    这是我的 Home Controller 代码,其余所有内容都设置在 Storyboard中(警报:C# Xamarin 语法)
    private List<UIViewController> viewControllers;
    
    public HomePageViewController (IntPtr handle) : base ( handle)
    {
    }
    
    public override void ViewDidLoad()
    {
        base.ViewDidLoad();
        var child1 = new UIViewController();
        child1.View.BackgroundColor = UIColor.Orange;
        var child2 = new UIViewController();
        child2.View.BackgroundColor = UIColor.Red;
        var child3 = new UIViewController();
        child3.View.BackgroundColor = UIColor.Green;
    
        this.viewControllers = new List<UIViewController>
        {
            child1,
            child2,
            child3,
        };
    
        this.SetViewControllers(new UIViewController[] { child1 }, UIPageViewControllerNavigationDirection.Forward, false, null);
    
        this.GetNextViewController = (c, r) =>
        {
            var current = this.viewControllers.IndexOf(this.ViewControllers[0]);
            if (current >= this.viewControllers.Count - 1)
                return null;
    
            return this.viewControllers[current + 1];
        };
    
        this.GetPreviousViewController = (c, r) =>
        {
            var current = this.viewControllers.IndexOf(this.ViewControllers[0]);
            if (current <= 0)
                return null;
    
            return this.viewControllers[current - 1];
        };
    }
    

    如何强制我的 child View Controller 具有全高(等于父容器的框架高度)?

    最佳答案

    我认为您可以使用代码和自定义布局来解决这个问题。我的意思是创建您的 UIPageViewController 并将其 View 插入到您的 UIViewController 代码中 而不是 Storyboard 。我觉得你
    应该覆盖 UIViewController.viewDidLayoutSubviews() 并“手动”设置您的矩形(至少是 UIPageViewController 之一。)好吧,当您在代码中执行此操作时,有时您甚至不需要覆盖 UIViewController.viewDidLayoutSubviews() 因为 Apple 本身的模板没有这样做.我认为因为任何创建的 View 都有 translatesAutoresizingMaskIntoConstraints = true 。所以你也可以遵循这个方法。

    当您创建一个新项目并声明它是 page based app 时,有一个示例。

    如果需要,这是模板(警告:这是 Apple 本身模板的一部分)

        var pageViewController: UIPageViewController?
    
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        // Configure the page view controller and add it as a child view controller.
        self.pageViewController = UIPageViewController(transitionStyle: .scroll, navigationOrientation: .horizontal, options: nil)
        self.pageViewController!.delegate = self
    
        let startingViewController: DataViewController = self.modelController.viewControllerAtIndex(0, storyboard: self.storyboard!)!
        let viewControllers = [startingViewController]
        self.pageViewController!.setViewControllers(viewControllers, direction: .forward, animated: false, completion: {done in })
    
        self.pageViewController!.dataSource = self.modelController
    
        self.addChildViewController(self.pageViewController!)
        self.view.addSubview(self.pageViewController!.view)
    
        // Set the page view controller's bounds using an inset rect so that self's view is visible around the edges of the pages.
        var pageViewRect = self.view.bounds
        if UIDevice.current.userInterfaceIdiom == .pad {
            pageViewRect = pageViewRect.insetBy(dx: 40.0, dy: 40.0)
        }
        self.pageViewController!.view.frame = pageViewRect
    
        self.pageViewController!.didMove(toParentViewController: self)
    }
    

    您可以通过扩展来扩展此功能

    关于uiscrollview - 带有滚动过渡样式的 UIPageViewController 自动为 iPhone X 添加安全区域插图,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/48513440/

    10-13 04:02