zoukankan      html  css  js  c++  java
  • CAScrollLayer

    CAScrollLayer

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

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

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

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

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

    清单6.10 用CAScrollLayer实现滑动视图

     1 #import "ScrollView.h"
     2 #import  @implementation ScrollView
     3 + (Class)layerClass
     4 {
     5     return [CAScrollLayer class];
     6 }
     7 
     8 - (void)setUp
     9 {
    10     //enable clipping
    11     self.layer.masksToBounds = YES;
    12 
    13     //attach pan gesture recognizer
    14     UIPanGestureRecognizer *recognizer = nil;
    15     recognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(pan:)];
    16     [self addGestureRecognizer:recognizer];
    17 }
    18 
    19 - (id)initWithFrame:(CGRect)frame
    20 {
    21     //this is called when view is created in code
    22     if ((self = [super initWithFrame:frame])) {
    23         [self setUp];
    24     }
    25     return self;
    26 }
    27 
    28 - (void)awakeFromNib {
    29     //this is called when view is created from a nib
    30     [self setUp];
    31 }
    32 
    33 - (void)pan:(UIPanGestureRecognizer *)recognizer
    34 {
    35     //get the offset by subtracting the pan gesture
    36     //translation from the current bounds origin
    37     CGPoint offset = self.bounds.origin;
    38     offset.x -= [recognizer translationInView:self].x;
    39     offset.y -= [recognizer translationInView:self].y;
    40 
    41     //scroll the layer
    42     [(CAScrollLayer *)self.layer scrollToPoint:offset];
    43 
    44     //reset the pan gesture translation
    45     [recognizer setTranslation:CGPointZero inView:self];
    46 }
    47 @end
    View Code

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

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

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

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

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

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

  • 相关阅读:
    openldap
    Java实现 洛谷 P1200 [USACO1.1]你的飞碟在这儿Your Ride Is He…
    Java实现 洛谷 P1200 [USACO1.1]你的飞碟在这儿Your Ride Is He…
    Java实现 洛谷 P2141 珠心算测验
    Java实现 洛谷 P2141 珠心算测验
    Java实现 洛谷 P2141 珠心算测验
    Java实现 洛谷 P2141 珠心算测验
    Java实现 洛谷 P2141 珠心算测验
    Java实现 洛谷 P1567 统计天数
    Java实现 洛谷 P1567 统计天数
  • 原文地址:https://www.cnblogs.com/EchoHG/p/7623747.html
Copyright © 2011-2022 走看看