开始使用UIScrollView

本文由Snow(博客)翻译自APPCODA。
原文: A Beginner’s Guide to UIScrollView
作者: joyce echessa

在iOS里,scroll views 是用来展示视图内容不能完全适配屏幕。Scroll views 有两个重要的目的:

  • 让用户把内容拖拽到他想展示的区域
  • 让用户通过夹得手势放大或缩小来展示内容

一个在iOS apps中经常用到的控件UITableView是UIScrollView的子类并且提供了很多方法展示超过屏幕的内容。

在这个教程里,我们将看到UIScrollView的很多方面,尤其是用代码或者Interface Builder创建scrollView,滚动、缩放、插入或内嵌scrollView。

在阅读前,先下载初始项目的包含文件,我们会在教程中使用到。

用代码创建Scroll View

Scroll views的创建和其他视图一样,无论代码还是Interface Builder。在那之后,只需要很少的配置就可以实现滚动的基础功能。
Scroll view被创建或插入到控制器里或其他视图里,完成Scroll View的配置只需要两个附加步骤:

  • 你必须为滚动内容的size设置 contentSize 属性,这会指定滚动区域的大小。
  • 你必须为scroll view添加一个或多个视图来展示或滚动。这些视图提供展示内容。

你可以为你的程序随意的配置任何可视的提示,像水平垂直滚动指示器,拖动弹跳,缩放弹跳,和滚动的方向约束。
我们从用代码创建滚动视图开始。从你下载的文件中打开ScrollViewDemo工程,在故事版中它包含了一个视图控制器连接到在程序中创建的ScrollViewController。我还包括了一个叫做image.png的图片,以后我们会用到(取自unsplash.com)。

打开ScrollViewController.swift并且添加以下属性。

var scrollView: UIScrollView!
var imageView: UIImageView!

如下展示修改 viewDidLoad() 。

override func viewDidLoad() {
    super.viewDidLoad()

    imageView = UIImageView(image: UIImage(named: "image.png"))

    scrollView = UIScrollView(frame: view.bounds)
    scrollView.backgroundColor = UIColor.blackColor()
    scrollView.contentSize = imageView.bounds.size
    scrollView.autoresizingMask = UIViewAutoresizing.FlexibleWidth | UIViewAutoresizing.FlexibleHeight

    scrollView.addSubview(imageView)
    view.addSubview(scrollView)
}

上面我们创建了一个滚动视图和一个图片视图。图片视图是滚动视图的子视图。contentSize设置滚动范围的大小。我们把他设置为等于图片的大小(2000 x 1500)。为了让图片有黑色的背景我们把滚动视图的背景色设为黑色。我们设置滚动视图的autoresizingMask(自动变换大小)属性为.FlexibleWidth 和 .FlexibleHeight以至于当设备旋转时可以重新调整他的大小。运行app然后你可以滚动并且看到图片的不同区域。

当你运行app时,你可能会发现图片的初始位置是在左上角。

这是因为滚动视图的初始点在(0,0),在左上角。如果你想在app启动时改变内容展示的位置,那你必须改变滚动视图的范围起始点。使用滚动视图时由于经常需要设置这个位置,你可以改变UIScrollView 的contentOffset属性来实现和改变初始位置同样的结果。

在设置滚动视图的autoresizingMask属性的语句下,粘贴下面的语句。

scrollView.contentOffset = CGPoint(x: 1000,y: 450)

再一次运行程序,你会看到滚动视图已经被移动到图片的另一个部分。这样你就可以决定当视图加载时展现在用户面前的是什么。

缩放

我们添加的滚动视图使用户能够滚动对屏幕来说太大的内容的大部分。这很好,但是如果用户可以缩放视图的大小它会变得更好用。

为了支持缩放,你必须为你的滚动视图设置一个委托。这个委托必须遵循UIScrollViewDelegate协议。这个协议必须实现viewForZoomingInScrollView()方法并且返回缩放的视图。

你也应该指定用户可以缩放的比例。你通过设置滚动视图的minimumZoomScale和maximumZoomScale属性来实现。
他们两个的默认值都是1.0。

像这样修改ScrollViewController类的定义。

class ScrollViewController: UIViewController,UIScrollViewDelegate {

然后把下面的方法添加到类里面。

func viewForZoomingInScrollView(scrollView: UIScrollView) -> UIView? {
    return imageView
}

然后在viewDidLoad()的底部添加如下代码。

scrollView.delegate = self  
scrollView.minimumZoomScale = 0.1
scrollView.maximumZoomScale = 4.0
scrollView.zoomScale = 1.0

在上面的代码中我们把zoomScale设为1.0,并且指定了缩放系数的最小和最大值。运行程序时,它会以预定的比例系数(比例系数是1.0)开始。当你用两指夹视图时,你可以在最大和最小比例系数中上下调整。我们为maximumZoomScale设置了一个大数(4.0),因此你可以调整图片到4倍它本身的大小。当你把缩放比例调高时,图片的大小大于原本的大小,图片就会变得模糊不清。我们在下一步会把它改回为默认的1.0 。

在上面,我们设置了minimumZoomScale为0.1,结果图片变得相当小以至于屏幕周围留下了很多空白。在风景模式,图片旁边的空白处更大。我们想让图片适配滚动视图,让它占用足够大的空间来展示图片。

为了做到这些,我们会通过滚动视图和图片的大小来计算最小比例。

先从viewDidLoad()移除以下三个参数。

scrollView.minimumZoomScale = 0.1
scrollView.maximumZoomScale = 4.0
scrollView.zoomScale = 1.0

然后为类添加下面的方法。我们拿到宽和高的比例并且找出较小的一个,把它设置为最小缩放比例。注意我们移除了maximumZoomScale的设置,让它可以恢复默认设置1.0 。

func setZoomScale() {
    let imageViewSize = imageView.bounds.size
    let scrollViewSize = scrollView.bounds.size
    let widthScale = scrollViewSize.width / imageViewSize.width
    let heightScale = scrollViewSize.height / imageViewSize.height

    scrollView.minimumZoomScale = min(widthScale,heightScale)
    scrollView.zoomScale = 1.0
}

然后在viewDidLoad()的结尾调用这个方法。

setZoomScale()

Also add the following so that the image scales right after the user tries to zoom in/out after a device orientation change.
也添加下面的方法,以确保设备改变方向后,用户可以正确的缩放图片的比例。

override func viewWillLayoutSubviews() {
    setZoomScale()
}

运行app,现在当你缩放图片时他会占用屏幕中足够的空间。

从上面的图片可以看出,滚动视图的内容-图片-是在屏幕的左上角的位置。我们想让它在屏幕的中间。

在类中添加如下方法。

func scrollViewDidZoom(scrollView: UIScrollView) {
    let imageViewSize = imageView.frame.size
    let scrollViewSize = scrollView.bounds.size

    let verticalPadding = imageViewSize.height < scrollViewSize.height ? (scrollViewSize.height - imageViewSize.height) / 2 : 0
    let horizontalPadding = imageViewSize.width < scrollViewSize.width ? (scrollViewSize.width - imageViewSize.width) / 2 : 0

    scrollView.contentInset = UIEdgeInsets(top: verticalPadding,left: horizontalPadding,bottom: verticalPadding,right: horizontalPadding)
}

每次缩放动作后这个方法被调用。它告诉委托滚动视图的缩放系数改变了。在上面的代码中我们计算了把图片放在中间需要填充或插入的大小,顶部和底部的值,我们检查图片的高是否比滚动视图小,如果是,填充两个视图差值的一半,如果不是,我们把设置为0.我们对水平方向做了同样的事情。然后我们设置滚动视图的contentInset。这是内容视图从闭合的滚动视图插入的距离。

运行app,现在当缩放到最小时内容会被放在最中间。

点击缩放

The basic UIScrollView class supports the pinch-in and pinch-out gestures with a little amount of additional code. But supporting a richer zooming experience using tap detection will rquire more work.
基础的UIScrollView类通过很少的代码实现夹得手势,但是用点击来支持更好的缩放体验需要更多的工作。
The iOS Human Interface Guidlines defines a double-tap to zoom in and out. This however assumes some constraints: that the view has a single level of zoom (such as in the Photos application where a double tap zooms the content up to the maximum zoom scale and another tap zooms it down to the mimimum),
在iOS Human Interface Guidelines 中定义了两次点击实现缩放。这当然假定一些约束条件:
视图只有一种缩放等级(比如在图片程序中,两次点击会把内容缩放到最大比例,再点击会把它缩放到最小比例)或者有效地两次点击会缩放到最大比例,实现后,下一次两次点击会返回满屏状态。但是一些程序在处理点击缩放时需要更灵活的表现,地图程序就是一个这样的例子。地图支持两次点击缩放,额外的两次点击会缩放的更深。为了缩放更大的比例,地图用两个手指触摸,当两个手指贴近到一起时,缩放到最小。

为了让你的程序支持点击缩放功能,你需要在类中实现UIScrollView的委托方法手势处理viewForZoomingInScrollView() ,这个类有责任追踪手指的数量和点击的数量。当它发现单击、双击、点击两次,它会因此回应。在点击两次并且有两个手指点击时,用代码实现以恰当比例缩放。

对于我们的程序,我们会执行点击两次时,如果当前是最小比例,则缩放到最大,反之缩放到最小。这和你在图片程序中看到的一样。

在类中添加下面两个方法。

func setupGestureRecognizer() {
    let doubleTap = UITapGestureRecognizer(target: self,action: "handleDoubleTap:")
    doubleTap.numberOfTapsRequired = 2
    scrollView.addGestureRecognizer(doubleTap)
}

func handleDoubleTap(recognizer: UITapGestureRecognizer) {

    if (scrollView.zoomScale > scrollView.minimumZoomScale) {
        scrollView.setZoomScale(scrollView.minimumZoomScale,animated: true)
    } else {
        scrollView.setZoomScale(scrollView.maximumZoomScale,animated: true)
    }
}

然后在viewDidLoad()的底部如下调用。

setupGestureRecognizer()

在上面的代码中,我们为滚动视图添加了一个手势识别器。它识别用户在屏幕上点击两次,我们处理缩放取决于当前的缩放情况。

运行app,你应该可以通过点击两次缩放。

相关文章

软件简介:蓝湖辅助工具,减少移动端开发中控件属性的复制和粘...
现实生活中,我们听到的声音都是时间连续的,我们称为这种信...
前言最近在B站上看到一个漂亮的仙女姐姐跳舞视频,循环看了亿...
【Android App】实战项目之仿抖音的短视频分享App(附源码和...
前言这一篇博客应该是我花时间最多的一次了,从2022年1月底至...
因为我既对接过session、cookie,也对接过JWT,今年因为工作...