CAScrollLayer(滚动图层)

作者: 莪的世界木有如果 | 来源:发表于2018-08-21 14:33 被阅读112次

    CAScrollLayer提供了和UIScrollView的基本功能。只不过它是layer,只负责显示,不响应用户事件,也不提供滚动条。

    GitHub项目地址 目录为:layer/scrollLayer

    想要CAScrollLayer实现滚动的效果,就要给CAScrollLayer所在的view上添加pan事件,通过scrollToPoint方法来实现CAScrollLayer的滚动。

    接下来让我们来用CAScrollLayer来常见一个基本的UIScrollView替代品。我们将会用CAScrollLayer作为视图的宿主图层,并创建一个自定义的UIView,然后用UIPanGestureRecognizer实现触摸事件响应。

    先看下效果图:

    scrollLayer.gif

    代码实现:

    • 首先创建一个继承于UIView的子类,见代码:
    #import "ScrollLayer.h"
    
    @implementation ScrollLayer
    
    +(Class)layerClass{
        return [CAScrollLayer class];
    }
    
    - (instancetype)initWithFrame:(CGRect)frame{
        self = [super initWithFrame: frame];
        if (self) {
            [self setUp];
        }
        return self;
    }
    
    - (void)awakeFromNib{
        [super awakeFromNib];
        [self setUp];
    }
    
    - (void)setUp{
        //允许剪切
        self.layer.masksToBounds = true;
        
        //给view添加UIPanGestureRecognizer
        UIPanGestureRecognizer * pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(pan:)];
        [self addGestureRecognizer:pan];
    }
    
    -(void)pan:(UIPanGestureRecognizer *)sender{
        //获取pan的变化点
        CGPoint translation = [sender translationInView:self];
        CGPoint offset = self.bounds.origin;
        NSLog(@"offset.x = %f offset.y = %f",offset.x,offset.y);
        NSLog(@"translation.x = %f translation.y = %f",translation.x,translation.y);
        //计算差值
        offset.x -= translation.x;
        offset.y -= translation.y;
        //scrollLayer滑动,这里其实是在改变self.layer的bounds的原点origin
        [(CAScrollLayer *)self.layer scrollToPoint:offset];
        //重置滑动的位移
        [sender setTranslation:CGPointZero inView:self];
    }
    

    在方法-(void)pan:(UIPanGestureRecognizer *)sender里面,主要思路是获取到layerboundsorigin。然后根据pan事件的变化点,设置offset的值,然后调用scrollToPoint:scrollToPoint:这个方法其实是改变layerboundsorigin的值,这个值一改变,就相当于layer的子视图产生了位移。
    例如:
    layer.bounds.origin = CGPointMake(-20,-20);
    这就说明layer的展示层原点为(-20,-20),如果子视图设置的frame为(0,0,100,100);则子视图的位置并不是靠着左、上边,而是分别距离20的边距。

    调用:

    //创建一个layer展示内容层,也就是scrollLayer的子视图
        CALayer * layer = [CALayer layer];
        layer.bounds = CGRectMake(0, 0, 300, 300);
        layer.position = CGPointMake(150, 100);
        layer.contents = (__bridge id)[UIImage imageNamed:@"reflection_image"].CGImage;
        
        //创建自定义的scrollLayer的view
        ScrollLayer *scrollLayer = [[ScrollLayer alloc] initWithFrame:CGRectMake(0, 0, 200, 200)];
        scrollLayer.layer.borderColor = [UIColor grayColor].CGColor;
        scrollLayer.layer.borderWidth = 1;
        
        scrollLayer.center = CGPointMake(kWidth/2, kHeight/2);
        [scrollLayer.layer addSublayer:layer];
        [self.view addSubview:scrollLayer];
    

    这里要注意的两点:

    • 1、就是CAScrollLayer不处理用户的输入,不负责将触摸事件转换为滑动事件,也不实现ios指定的行为;例如滑动反弹
    • 2、要注意bounds和frame的区别;frame是相对于父视图而言,在父视图的位置;bounds是针对自己而言,bounds的原点一般都为(0,0),设置bounds的原点,就相当于子视图的位置改变。

    下篇将说到CAEmitterLayer粒子引擎,用来创建实时的粒子动画:烟雾,火,雨,雪等。

    相关文章

      网友评论

        本文标题:CAScrollLayer(滚动图层)

        本文链接:https://www.haomeiwen.com/subject/eajdiftx.html