【iOS】仿喜馬拉雅首頁背景顏色漸變效果
阿新 • • 發佈:2020-06-24
前言
之前公司要求實現喜馬拉雅的首頁背景顏色漸變效果,於是花了一段時間實現了出來,在這裡記錄下,實現該效果主要用到了下面兩個庫: JXCategoryView一個功能強大的分類控制元件 GKCycleScrollView我自己寫的一個輪播圖控制元件
效果圖
先來看下效果圖:
說明
通過研究喜馬拉雅首頁你會發現,要實現該功能有三個地方需要注意
1、輪播圖的滑動(左右滑動背景顏色根據圖片漸變)
2、分類切換頁面(兩個頁面的當前背景色漸變)
3、頁面上下滑動(滑動到臨界位置後背景色不再根據輪播圖變化)
下面來說明下實現過程
JXCategoryView
裡面有個方法,傳入兩個顏色及漸變百分比,返回對應的漸變顏色,這裡直接用這個方法實現漸變
######1、輪播圖滑動
輪播圖用的GKCycleScrollView
// 滑動漸變背景色
- (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];
}
}
複製程式碼
2、分類切換頁面
監聽JXCategoryView的delegate方法,根據滑動距離找出當前頁面和下一個頁面及滑動百分比,漸變背景顏色
- (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];
}
}
}
複製程式碼
3、頁面上下滑動
監聽列表的上下滑動,根據滑動距離判斷是否到底臨界點,改變分類的背景色
- (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];
}
}
複製程式碼
######4、動態重新整理標題顏色和指示器顏色
關於動態改變標題顏色、指示器顏色JXCategoryView
並沒有提供相關方法,於是通過檢視相關程式碼,找到了下面的解決辦法,通過對JXCategoryTitleView
新增分類實現
- (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 上查閱相關程式碼。
最後
仿喜馬拉雅首頁背景顏色漸變效果很多APP都在用,如果你需要的話可以在GKXimalaya中檢視 如果您覺得還不錯,還請點個star,您的支援是我最大的動力。
讚賞
您的讚賞是對我最大的支援