使用UIScrollView循环浏览图像

时间:2015-06-29 14:16:20

标签: ios swift uiscrollview

Storyboard view of controller

我在scrollView中有一个imageView,我希望能够上传最多3个图像并让用户在它们之间滑动。我只是通过用我想要的信息替换视图的内容来实现这一点,但它看起来或感觉不如具有分页的滚动视图那样好。

我有所有代码可以在我想要的时候显示每个图像,但我的问题在于scrollview约束以及如何向具有固定宽度的scrollview添加更多内容。无论我做什么,当我向视图添加图像时,我似乎无法扩展滚动范围。

这是我现在正在尝试的事情:

let newImageView:UIImageView = UIImageView()
self.imageScrollView.contentSize = CGSize(width: self.imageView.frame.size.width * 3, height: self.imageView.frame.size.height)
self.imageScrollView.pagingEnabled = true

for i = 0; i < 3; ++i {
    var xOrigin:CGFloat = CGFloat(i) * self.view.frame.size.width
    newImageView.frame = CGRectMake(self.imageView.image!.size.width * i, 0, self.imageView.image!.size.width, self.imageScrollView.frame.size.height)
    newImageView.image = images[i]
    newImageView.contentMode = UIViewContentMode.ScaleAspectFit
    self.imageScrollView.addSubview(newImageView)
}

使用此代码我可以添加图像,但我无法滚动到它们。在我的故事板中,scrollview约束看起来像这样:

enter image description here

我确定其中一些限制是多余的,但我无法弄清楚为什么内容宽度不会延伸并允许我滚动浏览滚动视图中的所有图像。

修改

我使用@matt中的教科书示例进行了更改。我创建了一个新的视图控制器并将其放在我的另一个视图控制器中的视图中(与我原来的相同)。它显示第一个没有问题,但是当我向左或向右滑动时它似乎没有调用UIPageViewControllerDataSource函数。我不确定为什么会这样。

这是原始视图控制器(UploadPhotoViewController)中的样子

func setUpPageViewController() {
    sharedIm.images.append(UIImage(named: "placeholder")!)
    sharedIm.images.append(UIImage(named: "TestProfile")!)
    sharedIm.images.append(UIImage(named: "button")!)
    let pvc = UIPageViewController(transitionStyle: .Scroll, navigationOrientation: .Horizontal, options: nil)
    let page:ImagePage = ImagePage()
    pvc.dataSource = self
    pvc.setViewControllers([page], direction: .Forward, animated: false, completion: nil)

    pvc.view.frame = self.imageContainer.bounds
    self.imageContainer.addSubview(pvc.view)
    pvc.didMoveToParentViewController(self)
}

//this is placed at the end of the class
extension UploadPhotoViewController : UIPageViewControllerDataSource {
func pageViewController(pageViewController: UIPageViewController, viewControllerAfterViewController viewController: UIViewController) -> UIViewController? {
    let image = (viewController as! ImagePage).image
    let ix = find(sharedIm.images, image)! + 1
    println(ix)
    if ix >= sharedIm.images.count {
        println("no next page")
        return nil
    }
    sharedIm.currentIndex = ix
    let page = ImagePage()
    return page
}


func pageViewController(pageViewController: UIPageViewController, viewControllerBeforeViewController viewController: UIViewController) -> UIViewController? {
    let image = (viewController as! ImagePage).image
    let ix = find(sharedIm.images, image)! - 1
    println(ix)
    if ix < 0 {
        println("no previous page")
        return nil
    }
    sharedIm.currentIndex = ix
    let page = ImagePage()
    return page
}

以下是我的新视图控制器中添加到另一个视图中的内容:

class ImagePage: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {

var image : UIImage? 
var imagePicker: UIImagePickerController!
@IBOutlet var imageView : UIImageView!
@IBOutlet var forwardButton: UIButton!
@IBOutlet var backButton: UIButton!
@IBOutlet var closeButton: UIButton!
@IBOutlet var pictureButton: UIButton!
@IBOutlet var cameraButton: UIButton!



init() {
    self.image = sharedIm.images[sharedIm.currentIndex]
    super.init(nibName: "ImagePage", bundle: nil)
}

required init(coder: NSCoder) {
    fatalError("NSCoding not supported")
}

override func viewDidLoad() {
    super.viewDidLoad()
    self.imageView.image = self.image
}
//bunch of other code for buttons and uploading pictures
}

2 个答案:

答案 0 :(得分:3)

使用UIPageViewController(具有滚动样式),您尝试做的事情会轻松得多。我建议您切换到UIPageViewController实现。

原因是您一次只能提供一个“页面”(在您的情况下是一个图像)。您可以实时决定 是否在任一方向上都有另一个“页面”,以及您想要“真正”假装那些“页面”的数量。簿记工作发生在您的模型中(幕后数据),而不是您必须配置整个视图来同时处理所有页面,因为UIScrollView会让您这样做。

答案 1 :(得分:0)

使用autolayout和uiscrollview时,诀窍是知道何时加载内容。由于您正在以混合模式(帧和自动布局)工作,因此需要确保约束有时间加载,然后在加载后,您可以添加子视图并调整约束。如果您尝试在viewDidLoad上加载内容,则为时太早,您的约束可能尚未设置。如果您在viewWillAppear上加载内容,则为时已晚,并且已经锁定了约束以向用户显示视图。

所以,我发现加载内容的最佳位置是viewDidLayoutSubviews此时,autolayout已将约束应用于您的scrollView,您现在可以安全地进行更改。在这里添加一个调用来运行填充scrollView的代码,你应该没问题。此外,您需要设置一个标志以仅进行一次调用,因为在创建视图期间可以多次调用viewDidLayoutSubviews。您还应该在scrollView上调用setNeedsUpdateConstraints,以确保在添加子视图时更新其约束。