最近项目中用到了“图随表动”,如下图所示:
这是一个订单,需要add shipping insurance以上的部分随着表格的滚动而滚动,这里表格是group类型的,所以背景加在cell上是达不到效果的,在code4App上找到了一个例子(code4App中搜索“图随表动”),实现如下:
#define bgHeight table.frame.size.height
#define beginBgY -table.frame.size.height
- (void)addBgLayer{
UIImage *img = [UIImage imageNamed:@"bgTable.png"];
CGFloat imgHeight = img.size.height;
CGFloat contentHeight = table.contentSize.height;
NSInteger needNum = (contentHeight+bgHeight - beginBgY)/imgHeight + 1;
if (needNum > alreadyAddBg) {
for(int i = alreadyAddBg; i < needNum; i++) {
CGRect rect = CGRectMake(0, beginBgY+i*imgHeight, table.frame.size.width,imgHeight);
[self addLayerWithFrame:rect];
}
alreadyAddBg = needNum;
}
}
- (void)addLayerWithFrame:(CGRect)frame{
CALayer *background = [CALayer layer];
background.zPosition = -1;
background.frame = frame;
background.contents = (id)([[UIImage imageNamed:@"bgTable.png"] CGImage]);
[table.layer addSublayer:background];
}
其中beginBgY是背景的起始位置,如果你想从y小于0的位置开始也可以,代码很简单,不多做解释,就是加了个layer到table的layer上。
到这里初步达到了我的要求,但是,产品列表中的产品如果非常多的话,用户就必须要不停的往下翻,所以我将其弄成可以收缩的方式(之前有个收缩的demo:http://download.csdn.net/detail/sjx19871225/5086683)。
但是弄成收缩的之后,背景的大小又要随变化,我开始直接想把layer 给remove掉,然后重新添加,当然,结果是可以预见的,程序崩溃掉了,因为layer的引用计数已经只有1了,再remove当然就崩掉了。
我想了一个办法:因为从要求来看,只有列表部分的高度在变化,其他地方不变,所以背景的大小只有两种,这样我就定义了两个layer的成员变量并初始化分配内存,将背景图分别加在两个不一样大小的layer上,然后需要用哪个的时候就将哪个加载在table的layer上,将不用的remove掉,具体代码如下:
- (void)addBgLayer
{
UIImage *img0 = [UIImage imageNamed:@"tbg.png"];
UIImage *img1 = [UIImage imageNamed:@"pbg.png"];
UIImage *img2 = [UIImage imageNamed:@"bbg.png"];
CGFloat imgHeight = img1.size.height;
CGFloat contentHeightOpen = 0;;//减两个16是顶部和底部锯齿
CGFloat contentHeightNotOpen = 0;;
if (_order.isNewOrder)
{
contentHeightOpen = 90+[_order.productList count]*127+95+65+65+50*3-16-16;//减两个16是顶部和底部锯齿
contentHeightNotOpen = 90+95+65+65+50*3-16-16;
}else
{
contentHeightOpen = 90+[_order.productList count]*127+95+50*3-16-16;//减两个16是顶部和底部锯齿
contentHeightNotOpen = 90+95+50*3-16-16;
}
self.layerOpen.frame = EZRECT(0, 0, 320, contentHeightOpen);
self.layerNotOpen.frame =EZRECT(0, 0, 320, contentHeightOpen);
NSInteger needNum;
{//打开的layer
[self addLayerWithFrame:EZRECT(0, 0, 320, 16) withImage:img0 toLayer:self.layerOpen];
needNum = contentHeightOpen/imgHeight + 1+1;//为了美观,多加1个
for(int i = 0; i < needNum; i++) {
//CGRect rect = CGRectMake(0, beginBgY+i*imgHeight, 320,imgHeight);
CGRect rect = CGRectMake(0, i*imgHeight+16, 320,imgHeight);
[self addLayerWithFrame:rect withImage:img1 toLayer:self.layerOpen];
}
[self addLayerWithFrame:EZRECT(0, 16+needNum*imgHeight, 320, 16) withImage:img2 toLayer:self.layerOpen];
}
{//收起的layer
[self addLayerWithFrame:EZRECT(0, 0, 320, 16) withImage:img0 toLayer:self.layerNotOpen];
needNum = contentHeightNotOpen/imgHeight + 1+1;//为了美观,多加1个
for(int i = 0; i < needNum; i++)
{
//CGRect rect = CGRectMake(0, beginBgY+i*imgHeight, 320,imgHeight);
CGRect rect = CGRectMake(0, i*imgHeight+16, 320,imgHeight);
[self addLayerWithFrame:rect withImage:img1 toLayer:self.layerNotOpen];
}
[self addLayerWithFrame:EZRECT(0, 16+needNum*imgHeight, 320, 16) withImage:img2 toLayer:self.layerNotOpen];
}
BOOL isOpen = [[isOpenDic objectForKey:@"sectionProductList"] boolValue];
if (isOpen)
{
self.layerOpen.zPosition = -2;
[table.layer addSublayer:self.layerOpen];
}
else
{
self.layerNotOpen.zPosition = -2;
[table.layer addSublayer:self.layerNotOpen];
}
}
- (void)addLayerWithFrame:(CGRect)frame withImage:(UIImage *)image toLayer:(CALayer *)layer
{
CALayer *background = [CALayer layer];
background.zPosition = -1;
background.frame = frame;
background.contents = (id)([image CGImage]);
[layer addSublayer:background];
}
这里我又碰到了一个问题,就是
self.layerOpen.zPosition = -2;
图层的层次问题,注意到添加到table上的layer与添加到layerOpen(添加到table上的layer)层次是不同的。