以前公司要求实现喜马拉雅的首页背景颜色渐变效果,因而花了一段时间实现了出来,在这里记录下,实现该效果主要用到了下面两个库: JXCategoryView一个功能强大的分类控件 GKCycleScrollView我本身写的一个轮播图控件git
先来看下效果图: github
经过研究喜马拉雅首页你会发现,要实现该功能有三个地方须要注意 一、轮播图的滑动(左右滑动背景颜色根据图片渐变) 二、分类切换页面(两个页面的当前背景色渐变) 三、页面上下滑动(滑动到临界位置后背景色再也不根据轮播图变化) 下面来讲明下实现过程 JXCategoryView
里面有个方法,传入两个颜色及渐变百分比,返回对应的渐变颜色,这里直接用这个方法实现渐变bash
轮播图用的GKCycleScrollView
,须要监听UIScrollView的滑动,根据滑动的距离和方向,计算出当前图片和下一张图片以及渐变百分比,下面看下具体代码:微信
// 滑动渐变背景色 - (void)cycleScrollView:(GKCycleScrollView *)cycleScrollView didScroll:(UIScrollView *)scrollView { if (self.isCriticalPoint) return; CGFloat offsetX = scrollView.contentOffset.x; CGFloat maxW = self.bannerLists.count * scrollView.bounds.size.width; CGFloat changeOffsetX = offsetX - maxW; BOOL isFirstRight = NO; if (changeOffsetX < 0) { changeOffsetX = -changeOffsetX; isFirstRight = YES; } CGFloat ratio = (changeOffsetX / scrollView.bounds.size.width); // 超过了边界,不须要处理 if (ratio > self.bannerLists.count || ratio < 0) return; ratio = MAX(0, MIN(self.bannerLists.count, ratio)); NSInteger baseIndex = floorf(ratio); // 最后一个 if (baseIndex + 1 > self.bannerLists.count) { baseIndex = 0; } CGFloat remainderRatio = ratio - baseIndex; if (remainderRatio <= 0 || remainderRatio >= 1) return; GKHomeBannerModel *leftModel = self.bannerLists[baseIndex]; NSInteger nextIndex = 0; if (isFirstRight) { nextIndex = self.bannerLists.count - 1; }else if (baseIndex == self.bannerLists.count - 1) { nextIndex = 0; }else { nextIndex = baseIndex + 1; } GKHomeBannerModel *rightModel = self.bannerLists[nextIndex]; UIColor *leftColor = leftModel.headerBgColor ? leftModel.headerBgColor : GKHomeBGColor; UIColor *rightColor = rightModel.headerBgColor ? rightModel.headerBgColor : GKHomeBGColor; UIColor *color = [JXCategoryFactory interpolationColorFrom:leftColor to:rightColor percent:remainderRatio]; self.bgColor = color; if (self.isSelected && [self.delegate respondsToSelector:@selector(listVC:didChangeColor:)]) { [self.delegate listVC:self didChangeColor:color]; } } 复制代码
监听JXCategoryView的delegate方法,根据滑动距离找出当前页面和下一个页面及滑动百分比,渐变背景颜色markdown
- (void)categoryView:(JXCategoryBaseView *)categoryView scrollingFromLeftIndex:(NSInteger)leftIndex toRightIndex:(NSInteger)rightIndex ratio:(CGFloat)ratio { GKListViewController *leftVC = (GKListViewController *)self.containerView.validListDict[@(leftIndex)]; GKListViewController *rightVC = (GKListViewController *)self.containerView.validListDict[@(rightIndex)]; UIColor *leftColor = leftVC.isCriticalPoint ? [UIColor whiteColor] : leftVC.bgColor; UIColor *rightColor = rightVC.isCriticalPoint ? [UIColor whiteColor] : rightVC.bgColor; UIColor *color = [JXCategoryFactory interpolationColorFrom:leftColor to:rightColor percent:ratio]; self.headerBgView.backgroundColor = color; // 两边状态同样,不用改变 if (leftVC.isCriticalPoint == rightVC.isCriticalPoint) return; if (leftVC.isCriticalPoint) { if (ratio > 0.5) { [self changeToWhiteStateAtVC:nil]; }else { [self changeToBlackStateAtVC:nil]; } }else if (rightVC.isCriticalPoint) { if (ratio > 0.5) { [self changeToBlackStateAtVC:nil]; }else { [self changeToWhiteStateAtVC:nil]; } } } 复制代码
监听列表的上下滑动,根据滑动距离判断是否到底临界点,改变分类的背景色oop
- (void)listVC:(GKListViewController *)vc didScroll:(UIScrollView *)scrollView { if (self.style == GKHomeThemeStyleNone) return; CGFloat offsetY = scrollView.contentOffset.y; if (offsetY <= 0) return; if (offsetY > ADAPTATIONRATIO * 360.0f) { [self changeToBlackStateAtVC:vc]; }else { [self changeToWhiteStateAtVC:vc]; } } 复制代码
关于动态改变标题颜色、指示器颜色JXCategoryView
并无提供相关方法,因而经过查看相关代码,找到了下面的解决办法,经过对JXCategoryTitleView
添加分类实现ui
- (void)refreshCellState { [self.dataSource enumerateObjectsUsingBlock:^(JXCategoryBaseCellModel * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { [self reloadCellAtIndex:idx]; }]; CGRect selectedCellFrame = CGRectZero; JXCategoryIndicatorCellModel *selectedCellModel = nil; for (int i = 0; i < self.dataSource.count; i++) { JXCategoryIndicatorCellModel *cellModel = (JXCategoryIndicatorCellModel *)self.dataSource[i]; cellModel.sepratorLineShowEnabled = self.isSeparatorLineShowEnabled; cellModel.separatorLineColor = self.separatorLineColor; cellModel.separatorLineSize = self.separatorLineSize; cellModel.backgroundViewMaskFrame = CGRectZero; cellModel.cellBackgroundColorGradientEnabled = self.isCellBackgroundColorGradientEnabled; cellModel.cellBackgroundSelectedColor = self.cellBackgroundSelectedColor; cellModel.cellBackgroundUnselectedColor = self.cellBackgroundUnselectedColor; if (i == self.dataSource.count - 1) { cellModel.sepratorLineShowEnabled = NO; } if (i == self.selectedIndex) { selectedCellModel = cellModel; selectedCellFrame = [self getTargetCellFrame:i]; } } for (UIView<JXCategoryIndicatorProtocol> *indicator in self.indicators) { if (self.dataSource.count <= 0) { indicator.hidden = YES; }else { indicator.hidden = NO; JXCategoryIndicatorParamsModel *indicatorParamsModel = [[JXCategoryIndicatorParamsModel alloc] init]; indicatorParamsModel.selectedIndex = self.selectedIndex; indicatorParamsModel.selectedCellFrame = selectedCellFrame; [indicator jx_refreshState:indicatorParamsModel]; } } } 复制代码
到这里主要的功能点就已经实现了,固然还有不少细节,若是想了解,能够到github 上查阅相关代码。spa
仿喜马拉雅首页背景颜色渐变效果不少APP都在用,若是你须要的话能够在GKXimalaya中查看 若是您以为还不错,还请点个star,您的支持是我最大的动力。code
您的赞扬是对我最大的支持orm
![]() |
![]() |
---|