防止滑动 UIPageViewController 时出现的白色间隙
Preventing the white gap that appears on swiping UIPageViewController
我以这种方式实现了 UIPageViewController:
GalleryViewController
: 是PageViewController
的容器
PageViewController
: 是 pageViewController,我将它作为子视图添加到 GalleryViewController。
PageContentViewController
: 我把 UIImageView 放在里面作为 page view controller 的内容
一切顺利,但是当我在图像之间滑动时,奇怪的事情发生了。上方出现白色缺口
奇怪的是当我完成滚动时它会自动拉伸。
这是GalleryViewController
的代码,它是PageViewController的容器:
import UIKit
class PageViewController: UIViewController, UIPageViewControllerDataSource, UIPageViewControllerDelegate {
var startIndex:Int = 0
var pageViewController : UIPageViewController!
override func viewDidLoad() {
self.navigationController?.hidesBarsOnTap = true;
reset()
}
func reset() {
/* Getting the page View controller */
pageViewController = self.storyboard?.instantiateViewControllerWithIdentifier("PageViewController") as UIPageViewController
self.pageViewController.dataSource = self
let pageContentViewController = self.viewControllerAtIndex(0)
self.pageViewController.setViewControllers([pageContentViewController!], direction: UIPageViewControllerNavigationDirection.Forward, animated: true, completion: nil)
self.pageViewController.view.frame = CGRectMake(0, 0, self.view.frame.width, self.view.frame.height)
self.addChildViewController(pageViewController)
self.view.addSubview(pageViewController.view)
self.pageViewController.didMoveToParentViewController(self)
println("\(startIndex) start index")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func pageViewController(pageViewController: UIPageViewController, viewControllerAfterViewController viewController: UIViewController) -> UIViewController? {
var index = (viewController as PageContentViewController).pageIndex!
index++
if(index >= Constants.Statics.images.count){
return nil
}
return self.viewControllerAtIndex(index)
}
func pageViewController(pageViewController: UIPageViewController, viewControllerBeforeViewController viewController: UIViewController) -> UIViewController? {
var index = (viewController as PageContentViewController).pageIndex!
if(index <= 0){
return nil
}
index--
return self.viewControllerAtIndex(index)
}
func viewControllerAtIndex(index : Int) -> UIViewController? {
if((Constants.Statics.images.count == 0) || (index >= Constants.Statics.images.count)) {
return nil
}
let pageContentViewController = self.storyboard?.instantiateViewControllerWithIdentifier("PageContentViewController") as PageContentViewController
pageContentViewController.pageIndex = index
return pageContentViewController
}
}
我该怎么做才能防止滑动时出现拉伸和白色间隙?
更新:
奇怪的事情发生了,我把pageViewController的Transition Style改成了Page Curl
,问题没有出现。听起来像是关于滚动!
所以看起来在动画发生之前视图的框架不正确。尝试在它开始出现在屏幕上之前设置框架。类似于:
func pageViewController(pageViewController: UIPageViewController, viewControllerBeforeViewController viewController: UIViewController) -> UIViewController? {
var index = (viewController as PageContentViewController).pageIndex!
if(index <= 0){
return nil
}
index--
// Setting up the new view's frame
var newVC = self.viewControllerAtIndex(index)
newVC.view.frame = self.pageViewController.view.bounds
return newVC
}
自动拉伸是因为 ImageView 实例不受宽高比的限制。在您的 PageContentViewController
中,为您的图像指定 contentMode
值以解决此问题。例如:
self.imageView.contentMode = UIViewContentModeScaleAspectFit
你试过那些吗?您应该先 select 您的内容视图 控制器 。注意:点击控制器,不是视图
- 取消选中调整滚动视图插入
- 取消选中顶栏下方
- 取消选中底栏下方
看起来像是布局问题。
因为 UIPageViewController
和 .Scroll
类型使用 UIScrollView
来制作它,
尝试将 self.automaticallyAdjustsScrollViewInsets = false
添加到您的 viewDidLoad
如果还是不行,尝试移除self.navigationController?.hidesBarsOnTap = true
如果还是不行,请提供一个演示项目,这样我就可以找出问题所在。
错误的根源是您的 UIImageView 的约束。
当你开始滚动时,只调用viewWillAppear,还没有计算自动布局,当滚动完成,显示视图时,视图开始计算自动布局,viewDidAppear发生在自动布局完成后。
您可以通过在 PageContentViewController
中添加以下代码来检查
override func viewDidLoad() {
super.viewDidLoad()
imageView.image = UIImage(named: "UpcomingGamesBg")
println("viewDidLoad imageView Frame : \(imageView.frame) pageIndex : \(pageIndex)")
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
println("viewWillAppear imageView Frame : \(imageView.frame) pageIndex : \(pageIndex)")
}
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
println("viewDidAppear imageView Frame : \(imageView.frame) pageIndex : \(pageIndex)")
}
而且因为你的 imageView 的布局参考了 top layout guide,top layout guide 在计算自动布局前后可能有不同的值,所以你有这个错误。
所以要解决这个问题,您可以更改图像视图的约束并使它们相对于父视图(因为 pageContentViewController 就像一个子视图,而 pagerViewController 将管理顶部和底部边距),例如那:
有了它你可以修复这个错误,但要小心你应该给你的 pageViewController.view
添加一些约束
更新
例如要支持navigationBar / TabBar,你应该在viewDidLoad中添加一些约束(在view.addSubview(pageViewController.view)
之后):
pageViewController.view.setTranslatesAutoresizingMaskIntoConstraints(false)
let topConstraint = NSLayoutConstraint(item: pageViewController.view, attribute: NSLayoutAttribute.Top, relatedBy: NSLayoutRelation.Equal, toItem: topLayoutGuide, attribute: NSLayoutAttribute.Bottom, multiplier: 1.0, constant: 0)
let bottomConstaint = NSLayoutConstraint(item: pageViewController.view, attribute: NSLayoutAttribute.Bottom, relatedBy: NSLayoutRelation.Equal, toItem: bottomLayoutGuide, attribute: NSLayoutAttribute.Top, multiplier: 1.0, constant: 0)
let leadingConstraint = NSLayoutConstraint(item: pageViewController.view, attribute: NSLayoutAttribute.Leading, relatedBy: NSLayoutRelation.Equal, toItem: view, attribute: NSLayoutAttribute.Leading, multiplier: 1.0, constant: 0)
let trailingConstraint = NSLayoutConstraint(item: pageViewController.view, attribute: NSLayoutAttribute.Trailing, relatedBy: NSLayoutRelation.Equal, toItem: view, attribute: NSLayoutAttribute.Trailing, multiplier: 1.0, constant: 0)
view.addConstraints([topConstraint, bottomConstaint, leadingConstraint, trailingConstraint])
此致,
检查这里的例子:https://github.com/dimpiax/UIPageViewControllerScrolling
但是如果你想去除滑动时的空白,你可以去除反弹,例如:
for value in view.subviews {
if let scrollView = value as? UIScrollView {
scrollView.bounces = false
}
}
将 imageView 的 contentMode 设置为 AspectFill ...
我以这种方式实现了 UIPageViewController:
GalleryViewController
: 是PageViewController
PageViewController
: 是 pageViewController,我将它作为子视图添加到 GalleryViewController。
PageContentViewController
: 我把 UIImageView 放在里面作为 page view controller 的内容
一切顺利,但是当我在图像之间滑动时,奇怪的事情发生了。上方出现白色缺口
奇怪的是当我完成滚动时它会自动拉伸。
这是GalleryViewController
的代码,它是PageViewController的容器:
import UIKit
class PageViewController: UIViewController, UIPageViewControllerDataSource, UIPageViewControllerDelegate {
var startIndex:Int = 0
var pageViewController : UIPageViewController!
override func viewDidLoad() {
self.navigationController?.hidesBarsOnTap = true;
reset()
}
func reset() {
/* Getting the page View controller */
pageViewController = self.storyboard?.instantiateViewControllerWithIdentifier("PageViewController") as UIPageViewController
self.pageViewController.dataSource = self
let pageContentViewController = self.viewControllerAtIndex(0)
self.pageViewController.setViewControllers([pageContentViewController!], direction: UIPageViewControllerNavigationDirection.Forward, animated: true, completion: nil)
self.pageViewController.view.frame = CGRectMake(0, 0, self.view.frame.width, self.view.frame.height)
self.addChildViewController(pageViewController)
self.view.addSubview(pageViewController.view)
self.pageViewController.didMoveToParentViewController(self)
println("\(startIndex) start index")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func pageViewController(pageViewController: UIPageViewController, viewControllerAfterViewController viewController: UIViewController) -> UIViewController? {
var index = (viewController as PageContentViewController).pageIndex!
index++
if(index >= Constants.Statics.images.count){
return nil
}
return self.viewControllerAtIndex(index)
}
func pageViewController(pageViewController: UIPageViewController, viewControllerBeforeViewController viewController: UIViewController) -> UIViewController? {
var index = (viewController as PageContentViewController).pageIndex!
if(index <= 0){
return nil
}
index--
return self.viewControllerAtIndex(index)
}
func viewControllerAtIndex(index : Int) -> UIViewController? {
if((Constants.Statics.images.count == 0) || (index >= Constants.Statics.images.count)) {
return nil
}
let pageContentViewController = self.storyboard?.instantiateViewControllerWithIdentifier("PageContentViewController") as PageContentViewController
pageContentViewController.pageIndex = index
return pageContentViewController
}
}
我该怎么做才能防止滑动时出现拉伸和白色间隙?
更新:
奇怪的事情发生了,我把pageViewController的Transition Style改成了Page Curl
,问题没有出现。听起来像是关于滚动!
所以看起来在动画发生之前视图的框架不正确。尝试在它开始出现在屏幕上之前设置框架。类似于:
func pageViewController(pageViewController: UIPageViewController, viewControllerBeforeViewController viewController: UIViewController) -> UIViewController? {
var index = (viewController as PageContentViewController).pageIndex!
if(index <= 0){
return nil
}
index--
// Setting up the new view's frame
var newVC = self.viewControllerAtIndex(index)
newVC.view.frame = self.pageViewController.view.bounds
return newVC
}
自动拉伸是因为 ImageView 实例不受宽高比的限制。在您的 PageContentViewController
中,为您的图像指定 contentMode
值以解决此问题。例如:
self.imageView.contentMode = UIViewContentModeScaleAspectFit
你试过那些吗?您应该先 select 您的内容视图 控制器 。注意:点击控制器,不是视图
- 取消选中调整滚动视图插入
- 取消选中顶栏下方
- 取消选中底栏下方
看起来像是布局问题。
因为 UIPageViewController
和 .Scroll
类型使用 UIScrollView
来制作它,
尝试将 self.automaticallyAdjustsScrollViewInsets = false
添加到您的 viewDidLoad
如果还是不行,尝试移除self.navigationController?.hidesBarsOnTap = true
如果还是不行,请提供一个演示项目,这样我就可以找出问题所在。
错误的根源是您的 UIImageView 的约束。
当你开始滚动时,只调用viewWillAppear,还没有计算自动布局,当滚动完成,显示视图时,视图开始计算自动布局,viewDidAppear发生在自动布局完成后。
您可以通过在 PageContentViewController
override func viewDidLoad() {
super.viewDidLoad()
imageView.image = UIImage(named: "UpcomingGamesBg")
println("viewDidLoad imageView Frame : \(imageView.frame) pageIndex : \(pageIndex)")
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
println("viewWillAppear imageView Frame : \(imageView.frame) pageIndex : \(pageIndex)")
}
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
println("viewDidAppear imageView Frame : \(imageView.frame) pageIndex : \(pageIndex)")
}
而且因为你的 imageView 的布局参考了 top layout guide,top layout guide 在计算自动布局前后可能有不同的值,所以你有这个错误。
所以要解决这个问题,您可以更改图像视图的约束并使它们相对于父视图(因为 pageContentViewController 就像一个子视图,而 pagerViewController 将管理顶部和底部边距),例如那:
有了它你可以修复这个错误,但要小心你应该给你的 pageViewController.view
添加一些约束更新
例如要支持navigationBar / TabBar,你应该在viewDidLoad中添加一些约束(在view.addSubview(pageViewController.view)
之后):
pageViewController.view.setTranslatesAutoresizingMaskIntoConstraints(false)
let topConstraint = NSLayoutConstraint(item: pageViewController.view, attribute: NSLayoutAttribute.Top, relatedBy: NSLayoutRelation.Equal, toItem: topLayoutGuide, attribute: NSLayoutAttribute.Bottom, multiplier: 1.0, constant: 0)
let bottomConstaint = NSLayoutConstraint(item: pageViewController.view, attribute: NSLayoutAttribute.Bottom, relatedBy: NSLayoutRelation.Equal, toItem: bottomLayoutGuide, attribute: NSLayoutAttribute.Top, multiplier: 1.0, constant: 0)
let leadingConstraint = NSLayoutConstraint(item: pageViewController.view, attribute: NSLayoutAttribute.Leading, relatedBy: NSLayoutRelation.Equal, toItem: view, attribute: NSLayoutAttribute.Leading, multiplier: 1.0, constant: 0)
let trailingConstraint = NSLayoutConstraint(item: pageViewController.view, attribute: NSLayoutAttribute.Trailing, relatedBy: NSLayoutRelation.Equal, toItem: view, attribute: NSLayoutAttribute.Trailing, multiplier: 1.0, constant: 0)
view.addConstraints([topConstraint, bottomConstaint, leadingConstraint, trailingConstraint])
此致,
检查这里的例子:https://github.com/dimpiax/UIPageViewControllerScrolling
但是如果你想去除滑动时的空白,你可以去除反弹,例如:
for value in view.subviews {
if let scrollView = value as? UIScrollView {
scrollView.bounces = false
}
}
将 imageView 的 contentMode 设置为 AspectFill ...