[toc]
故事背景
- 产品经理:巴拉巴拉,巴拉巴拉,巴拉巴拉。。。。
- 我:你在讲什么,我一句没听懂,能不能表达清楚一点
- 产品经理:你手机有装天猫吗?
- 我:没有???(我在想应该是从天猫哪里仿过来的)
- 产品经理:我给你看一下吧,就是要做这种效果,能做吗?
- 我:能做(就是这么自信),我先跟 Android 和 H5 开发沟通一下!!!
需求分析
- banner切换的时候,改变 banner 背景区域颜色颜色
- banner 按页滚动
- 在没有手势的情况下,2 秒 banner 自动切换
- 支持手动滑动切换
- 手势开始触摸 banner,停止自动切换
- 手势停止触摸,开始自动切换
- 当前背景颜色 = 当前页banner对应的背景颜色 + (下一页banner 对应背景颜色 - 当前页banner对应的背景颜色)* 下一页banner相对于父视图可见区域的比例
- banner 和 banner 的背景颜色都是运营配置并下发的客户端的
实现思路
假设有 bannerList 和 bannerBackgroundColorList 两个列表, bannerList 中装的是 banner 数据,bannerBackgroundColorList 中装的是每一个 banner 对应的背景颜色数据,每一个 banner 对应一个 color
NSArray *bannerList = @[banner1, banner2, banner3, banner4];
NSArray *bannerBackgroundColorList = @[color1, color2, color3, color4];
实现ScrollView 的代理,监听滑动过程,实现如下方法
- (void)scrollDidScroll:(UIScrollView *)scrollView {
//...
}
取得开始页和结束页背景颜色
取得当前页
NSInteger startPage = scrollView.contentOffset.x / scrollView.width;
UIColor *startColor = bannerBackgroundColorList[startPage];
取得将要显示的下一页
NSInteger nextPage = startPage + 1;
if (nextPage >= bannerBackgroundColorList.count){
nextPage = 0;
}
UIColor *endColor = bannerBackgroundColorList[nextPage];
取得结束页出现的比例,计算公式如下
p = (scrollView.offset.x%scrollView.width)/scrollView.width
scrollView.offset.x 为滚动视图的 x 方向的偏移量,scrollView.width 为滚动视图的宽度
将取得颜色转换为RGBA色值
如果颜色本身是一个后端传递过来的 16 进制色值,则采用下面的方式
/** 提取十六进制字符串中的色值 */
BOOL YSYHexStrToRGBA(NSString *str,
NSInteger *r, NSInteger *g, NSInteger *b, NSInteger *a) {
str = [str uppercaseString];
if ([str hasPrefix:@"#"]) {
str = [str substringFromIndex:1];
} else if ([str hasPrefix:@"0X"]) {
str = [str substringFromIndex:2];
}
NSUInteger length = [str length];
// RGB RGBA RRGGBB RRGGBBAA
if (length != 3 && length != 4 && length != 6 && length != 8) {
return NO;
}
//RGB,RGBA,RRGGBB,RRGGBBAA
if (length < 5) {
*r = YSYHexStrToInt([str substringWithRange:NSMakeRange(0, 1)]);
*g = YSYHexStrToInt([str substringWithRange:NSMakeRange(1, 1)]);
*b = YSYHexStrToInt([str substringWithRange:NSMakeRange(2, 1)]);
if (length == 4){
*a = YSYHexStrToInt([str substringWithRange:NSMakeRange(3, 1)]);
} else {
*a = 255;
}
} else {
*r = YSYHexStrToInt([str substringWithRange:NSMakeRange(0, 2)]);
*g = YSYHexStrToInt([str substringWithRange:NSMakeRange(2, 2)]);
*b = YSYHexStrToInt([str substringWithRange:NSMakeRange(4, 2)]);
if (length == 8) {
*a = YSYHexStrToInt([str substringWithRange:NSMakeRange(6, 2)]);
} else {
*a = 255;
}
}
return YES;
}
如果颜色是一个 UIColor 类型的对象则采用 UIColor 类提供的方法
- (BOOL)getRed:(CGFloat *)R green: (CGFloat *)G blue:(CGFloat *)B alpha:(CGFloat *)A
这里假设bannerBackgroundColorList 里的元素 UIColor 类型的
CGFloat startR,startG,startB,startA,endR,endG,endB,endA;
[startColor getRed:&startR green:&startG blue:&startB alpha:&startA];
[endColor getRed:&endR green:&endG blue:&endB alpha:&endA];
计算最终色值
R = startR + (endR - starR) * p;
G = startG + (endG - starG) * p;
B = startB + (endB - starB) * p;
A = startA + (endA - starA) * p;
将计算出来的色值转换为颜色,得到 banner 背景当前要显示的颜色
UIColor *currentColor = [UIColor colorWithRed:R green:G blue:B alpha:A];
总结
- 为了方便 banner 切换我这里使用 GitHub 开源库 SDCycleScrollView,挺好用的
- 技术要点就是取两个颜色的中间颜色,颜色由R、G、B、A构成(准确一点来说是由 R、G、B 三色值构成),取中间颜色,也就是对开始颜色的RGBA值跟结束颜色的RGBA值进行运算得到最终的RGBA色值,将色值再转换为颜色