CAScrollLayer

对于一个未转换的图层,它的bounds和它的frame是一样的,frame属性是由bounds属性自动计算而出的,所以更改任意一个值都会更新其他值。

但是如果你只想显示一个大图层里面的一小部分呢。比如说,你可能有一个很大的图片,你希望用户能够随意滑动,或者是一个数据或文本的长列表。在一个典型的iOS应用中,你可能会用到UITableView或是UIScrollView,但是对于独立的图层来说,什么会等价于刚刚提到的UITableView和UIScrollView呢?

在第二章中,我们探索了图层的contentsRect属性的用法,它的确是能够解决在图层中小地方显示大图片的解决方法。但是如果你的图层包含子图层那它就不是一个非常好的解决方案,因为,这样做的话每次你想『滑动』可视区域的时候,你就需要手工重新计算并更新所有的子图层位置。

这个时候就需要CAScrollLayer了。CAScrollLayer有一个-scrollToPoint:方法,它自动适应bounds的原点以便图层内容出现在滑动的地方。注意,这就是它做的所有事情。前面提到过,Core Animation并不处理用户输入,所以CAScrollLayer并不负责将触摸事件转换为滑动事件,既不渲染滚动条,也不实现任何iOS指定行为例如滑动反弹(当视图滑动超多了它的边界的将会反弹回正确的地方)。

让我们来用CAScrollLayer来常见一个基本的UIScrollView替代品。我们将会用CAScrollLayer作为视图的宿主图层,并创建一个自定义的UIView,然后用UIPanGestureRecognizer实现触摸事件响应。这段代码见清单6.10. 图6.11是运行效果:ScrollView显示了一个大于它的frame的UIImageView。

清单6.10 用CAScrollLayer实现滑动视图

 #import "ScrollView.h"
#import @implementation ScrollView
+ (Class)layerClass
{
return [CAScrollLayer class];
} - (void)setUp
{
//enable clipping
self.layer.masksToBounds = YES; //attach pan gesture recognizer
UIPanGestureRecognizer *recognizer = nil;
recognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(pan:)];
[self addGestureRecognizer:recognizer];
} - (id)initWithFrame:(CGRect)frame
{
//this is called when view is created in code
if ((self = [super initWithFrame:frame])) {
[self setUp];
}
return self;
} - (void)awakeFromNib {
//this is called when view is created from a nib
[self setUp];
} - (void)pan:(UIPanGestureRecognizer *)recognizer
{
//get the offset by subtracting the pan gesture
//translation from the current bounds origin
CGPoint offset = self.bounds.origin;
offset.x -= [recognizer translationInView:self].x;
offset.y -= [recognizer translationInView:self].y; //scroll the layer
[(CAScrollLayer *)self.layer scrollToPoint:offset]; //reset the pan gesture translation
[recognizer setTranslation:CGPointZero inView:self];
}
@end

图6.11 用UIScrollView创建一个凑合的滑动视图

不同于UIScrollView,我们定制的滑动视图类并没有实现任何形式的边界检查(bounds checking)。图层内容极有可能滑出视图的边界并无限滑下去。CAScrollLayer并没有等同于UIScrollView中contentSize的属性,所以当CAScrollLayer滑动的时候完全没有一个全局的可滑动区域的概念,也无法自适应它的边界原点至你指定的值。它之所以不能自适应边界大小是因为它不需要,内容完全可以超过边界。

那你一定会奇怪用CAScrollLayer的意义到底何在,因为你可以简单地用一个普通的CALayer然后手动适应边界原点啊。真相其实并不复杂,UIScrollView并没有用CAScrollLayer,事实上,就是简单的通过直接操作图层边界来实现滑动。

CAScrollLayer有一个潜在的有用特性。如果你查看CAScrollLayer的头文件,你就会注意到有一个扩展分类实现了一些方法和属性:

 - (void)scrollPoint:(CGPoint)p;
- (void)scrollRectToVisible:(CGRect)r;
@property(readonly) CGRect visibleRect;

看到这些方法和属性名,你也许会以为这些方法给每个CALayer实例增加了滑动功能。但是事实上他们只是放置在CAScrollLayer中的图层的实用方法。scrollPoint:方法从图层树中查找并找到第一个可用的CAScrollLayer,然后滑动它使得指定点成为可视的。scrollRectToVisible:方法实现了同样的事情只不过是作用在一个矩形上的。visibleRect属性决定图层(如果存在的话)的哪部分是当前的可视区域。如果你自己实现这些方法就会相对容易明白一点,但是CAScrollLayer帮你省了这些麻烦,所以当涉及到实现图层滑动的时候就可以用上了。

CAScrollLayer的更多相关文章

  1. iOS之CAScrollLayer属性简介和使用

    1.CAScrollLayer的简介 CAScrollLayer用于显示一个滑动图层的一部分,可以确定滑动方向和可视区域面积,限制不滑出区域外!相关属性如下:其中 /* Scroll the cont ...

  2. ios项目里扒出来的json文件

    p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 13.0px Menlo; color: #000000 } p.p2 { margin: 0.0px 0. ...

  3. Github上关于iOS的各种开源项目集合(强烈建议大家收藏,查看,总有一款你需要)

    下拉刷新 EGOTableViewPullRefresh - 最早的下拉刷新控件. SVPullToRefresh - 下拉刷新控件. MJRefresh - 仅需一行代码就可以为UITableVie ...

  4. IOS Core Animation Advanced Techniques的学习笔记(五)

    第六章:Specialized Layers   类别 用途 CAEmitterLayer 用于实现基于Core Animation粒子发射系统.发射器层对象控制粒子的生成和起源 CAGradient ...

  5. iOS - 开发类库

    开发类库   UI 项目名称 项目信息 1.MJRefresh 仅需一行代码就可以为UITableView或者CollectionView加上下拉刷新或者上拉刷新功能.可以自定义上下拉刷新的文字说明. ...

  6. iOS及Mac开源项目和学习资料【超级全面】

    UI 下拉刷新 EGOTableViewPullRefresh – 最早的下拉刷新控件. SVPullToRefresh – 下拉刷新控件. MJRefresh – 仅需一行代码就可以为UITable ...

  7. Core Animation编程指南

    本文是<Core Animation Programming Guide>2013-01-28更新版本的译文.本文略去了原文中关于OS X平台上Core Animation相关内容.因为原 ...

  8. iOS:iOS开发非常全的三方库、插件等等

    iOS开发非常全的三方库.插件等等 github排名:https://github.com/trending, github搜索:https://github.com/search. 此文章转自git ...

  9. CALayer的分析

    转载地址:  http://my.oschina.net/u/2340880/blog/536048 iOS开发CoreAnimation解读之二——对CALayer的分析 一.UIView中的CAL ...

随机推荐

  1. [VS]VS2010如何使用Visual Studio Online在线服务管理团队资源(在线TFS)

    前言 Visual Studio Online,也就是以前的Team Foundation Service,从名字可以看出这是一个团队资源管理服务.在微软的云基础架构中运行,无需安装或配置任何服务器, ...

  2. CentOS6 防火墙配置

    清空现有的规则 iptables -F iptables -P INPUT DROP iptables -I INPUT -m state --state RELATED , ESTABLISHED ...

  3. 兵器簿之Alcatraz(插件管理神器)的配置和使用

    Alcatraz是一款开源框架,帮助我们管理和安装Xcode需要的一些插件,很赞,安装也很简单: 终端输入: curl -fsSL https://raw.githubusercontent.com/ ...

  4. vue--获取监听获取radius的改变

    做一个考试系统,单选题都是后台来的数据,所以一时间没有想到 @change这个方法: <template> <div id="Home"> <v-he ...

  5. thinkphp---设置路由

    在做一个项目,在项目完成之后,配置一下路由,让URL更容易美观. 下面是具体的配置: Common / Conf / config.php // 路由处理 'URL_HTML_SUFFIX'=> ...

  6. 转基于概率的矩阵分解原理详解(PMF)

    上一篇博客讲到了推荐系统中常用的矩阵分解方法,RegularizedMF是对BasicMF的优化,而PMF是在RegularizedMF的基础上,引入概率模型进一步优化.假设用户U和项目V的特征矩阵均 ...

  7. Print or Cout an Unsigned Char Variable 打印无符号字符

    在C++中,unsigned char用来表示一个字节,也就是8位大小的值,那么我们如何来打印出其值呢,用cout直接打印会乱码,我们可以通过下面两种方法来打印: cout << stat ...

  8. thinkphp与php共享session

    在其他php页面添加如下代码即可 if (!session_id()) session_start(); 使用时 thinphp 使用 session('test','123'); $user_inf ...

  9. JAVA中域、方法、类的可见性

    多态在域的问题上是特殊的.我理解不了中文版的书直接叫域,看了英文原版,原版写的是fields,直接翻译虽然没错,但是出问题的变量不是域.特地查了what is the meaning of field ...

  10. Java 构造函数(抽象类中的构造函数) 和 加载

    博客分类: 面向对象设计的原则 与 概念   1. Java 的构造函数 与初始化块: a. 抽象类的构造函数 若果在父类中(也就是抽象类)中显示的写了有参数的构造函数,在子类是就必须写一个构造函数来 ...