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
里面,主要思路是获取到layer
的bounds
的origin
。然后根据pan事件的变化点,设置offset的值,然后调用scrollToPoint:
。scrollToPoint:
这个方法其实是改变layer
的bounds
的origin
的值,这个值一改变,就相当于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粒子引擎,用来创建实时的粒子动画:烟雾,火,雨,雪等。
网友评论