【iOS】仿喜馬拉雅首頁背景顏色漸變效果

前言

之前公司要求實(shí)現(xiàn)喜馬拉雅的首頁背景顏色漸變效果,于是花了一段時(shí)間實(shí)現(xiàn)了出來,在這里記錄下,實(shí)現(xiàn)該效果主要用到了下面兩個(gè)庫:
JXCategoryView一個(gè)功能強(qiáng)大的分類控件
GKCycleScrollView我自己寫的一個(gè)輪播圖控件

效果圖

先來看下效果圖:


xmly.gif

說明

通過研究喜馬拉雅首頁你會發(fā)現(xiàn),要實(shí)現(xiàn)該功能有三個(gè)地方需要注意
1、輪播圖的滑動(左右滑動背景顏色根據(jù)圖片漸變)
2、分類切換頁面(兩個(gè)頁面的當(dāng)前背景色漸變)
3、頁面上下滑動(滑動到臨界位置后背景色不再根據(jù)輪播圖變化)
下面來說明下實(shí)現(xiàn)過程
JXCategoryView里面有個(gè)方法,傳入兩個(gè)顏色及漸變百分比,返回對應(yīng)的漸變顏色,這里直接用這個(gè)方法實(shí)現(xiàn)漸變

1、輪播圖滑動

輪播圖用的GKCycleScrollView,需要監(jiān)聽UIScrollView的滑動,根據(jù)滑動的距離和方向,計(jì)算出當(dāng)前圖片和下一張圖片以及漸變百分比,下面看下具體代碼:

// 滑動漸變背景色
- (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);
    
    // 最后一個(gè)
    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、分類切換頁面

監(jiān)聽JXCategoryView的delegate方法,根據(jù)滑動距離找出當(dāng)前頁面和下一個(gè)頁面及滑動百分比,漸變背景顏色

- (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;
    
    // 兩邊狀態(tài)一樣,不用改變
    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、頁面上下滑動

監(jiān)聽列表的上下滑動,根據(jù)滑動距離判斷是否到底臨界點(diǎn),改變分類的背景色

- (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、動態(tài)刷新標(biāo)題顏色和指示器顏色

關(guān)于動態(tài)改變標(biāo)題顏色、指示器顏色JXCategoryView并沒有提供相關(guān)方法,于是通過查看相關(guān)代碼,找到了下面的解決辦法,通過對JXCategoryTitleView添加分類實(shí)現(xiàn)

- (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];
        }
    }
}

到這里主要的功能點(diǎn)就已經(jīng)實(shí)現(xiàn)了,當(dāng)然還有很多細(xì)節(jié),如果想了解,可以到github 上查閱相關(guān)代碼。

最后

仿喜馬拉雅首頁背景顏色漸變效果很多APP都在用,如果你需要的話可以在GKXimalaya中查看
如果您覺得還不錯,還請點(diǎn)個(gè)star,您的支持是我最大的動力。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容