【乾貨】每個APP都用得上的SegmentView

金字塔程式設計師發表於2018-08-15

JXCategoryView.png

騰訊新聞今日頭條、QQ音樂、網易雲音樂、京東、愛奇藝、淘寶、天貓、簡書、微博等所有主流APP分類切換滾動檢視

與其他的同類三方庫對比的優點:

  • 使用POP(Protocol Oriented Programming面對協議程式設計)封裝指示器邏輯,可以為所欲為的自定義指示器效果;
  • 提供更加全面豐富的效果,互動更加順暢;
  • 使用子類化管理cell樣式,邏輯更清晰,擴充套件更簡單;

Github地址

下載原始碼,一睹為快!JXCategoryView

效果預覽

指示器效果預覽

說明 Gif
指示器LineView
LineView.gif
指示器LineView京東風格
JDLineStyle.gif
指示器LineView愛奇藝風格
IQIYILineStyle.gif
指示器EllipseLayer
BackgroundEllipseLayer.gif
指示器EllipseLayer遮罩
TitleMask.gif
指示器EllipseLayer遮罩 (陰影)
BackgroundViewShadow.gif
指示器ImageView(小船)
IndicatorImageView.gif
指示器滾動效果(足球)
Football.gif
QQ黏性紅點
QQBall.gif
三角形底部
TriangleBottom.gif
三角形頂部
TriangleTop.gif
文字遮罩(無背景檢視)
TitleMaskNoBackgroundView.gif
背景指示圖
BackgroundImageView.gif
矩形指示圖
Rectangle.gif
混合使用
Mixed.gif
自定義Indicator示例-點線
IndicatorCustomizeGuide.gif

Cell樣式效果預覽

說明 Gif
顏色漸變
TitleColorGradient.gif
大小縮放
Zoom.gif
分割線
SeparatorLine.gif
TitleImage_Top
TitleImageTop.gif
TitleImage_Left
TitleImageLeft.gif
TitleImage_Bottom
TitleImageBottom.gif
TitleImage_Right
TitleImageRight.gif
TitleImage_OnlyImage
TitleImageOnlyImage.gif
圖文混用
CellMixed.gif
自定義-數字
Number.gif
自定義cell-紅點
CellRedDot.gif
自定義cell-背景色漸變
CellBackgroundColorGradient.gif
騰訊視訊效果
TXVedio.gif
自定義cell示例-多行+富文字
AttributeView.gif

特殊效果預覽

說明 Gif
SegmentedControl
SegmentedControl.gif
導航欄使用
SegmentedControlNavi.gif
個人主頁(上下左右滾動、header懸浮)
UserProfile.gif
巢狀使用
Nest.gif
垂直列表滾動
高仿騰訊視訊
(背景色異常是錄屏軟體bug
VerticalList.gif
資料來源重新整理&列表資料載入 示例
LoadData.gif

要求

  • iOS 8.0+
  • Xcode 9+
  • Objective-C

安裝

手動

Clone程式碼,把Sources資料夾拖入專案,#import "JXCategoryView.h",就可以使用了;

CocoaPods

target '<Your Target Name>' do
    pod 'JXCategoryView'
end
複製程式碼

結構圖

JXCategoryViewStructure.png

  • 指示器樣式自定義:使用POP(Protocol Oriented Programming面對協議程式設計)封裝指示器邏輯,只要遵從JXCategoryIndicatorProtocol協議,就可以實現你的指示器效果。參考:JXCategoryIndicatorLineView;
  • Cell樣式自定義:使用子類化,基類搭建基礎,子類實現特殊效果。便於程式碼管理,功能擴充套件;參考:JXCategoryNumberView;

特殊說明

  • 自定義:即使提供了靈活擴充套件,我的原始碼也不可能滿足所有情況,建議大家可以通過fork倉庫,維護自己的一套效果。也可以直接拖入原始檔進行修改。
  • 個人主頁效果:上下左右滾動且HeaderView懸浮的實現,用的是我寫的這個庫JXPagingView
  • 垂直列表滾動:參考demo工程的VerticalListViewController,未做功能封裝,參考裡面的程式碼做,多注意註釋,就可以實現了。

POP說明

通過將指示器的行為抽象出來,再通過JXCategoryIndicatorProtocol協議進行約束。這樣指示器效果就可以無限擴充套件,為所欲為的新增指示器了,不再受上一個版本繼承的束縛了。更多POP內容,推薦喵神的文章面向協議程式設計與 Cocoa 的邂逅

常用屬性說明

JXCategoryView常用屬性說明

屬性 說明
defaultSelectedIndex 預設選中的index,用於初始化時指定選中某個index
selectedIndex 只讀屬性,當前選中的index
cellWidth cell的寬度,預設:JXCategoryViewAutomaticDimension
cellSpacing cell之間的間距,預設20
cellWidthIncrement cell寬度的補償值,預設0
averageCellWidthEnabled 當cell內容總寬度小於JXCategoryBaseView的寬度,是否將cellWidth均分。預設為YES。
contentScrollView 需要關聯的contentScrollView,內部監聽contentOffset

Cell樣式常用屬性說明

屬性 說明
titleColor titleLabel未選中顏色 預設:[UIColor blackColor]
titleSelectedColor titleLabel選中顏色 預設:[UIColor redColor]
titleFont titleLabel的字型 預設:[UIFont systemFontOfSize:15]
titleColorGradientEnabled title的顏色是否漸變過渡 預設:NO
titleLabelMaskEnabled titleLabel是否遮罩過濾 預設:NO
titleLabelZoomEnabled titleLabel是否縮放 預設:NO
titleLabelZoomScale citleLabel縮放比例 預設:1.2
imageZoomEnabled imageView是否縮放 預設:NO
imageZoomScale imageView縮放比例 預設:1.2
separatorLineShowEnabled cell分割線是否展示 預設:NO (顏色、寬高可以設定)
JXCategoryTitleImageType 圖片所在位置:上面、左邊、下面、右邊 預設:左邊

指示器常用屬性說明

屬性 說明
JXCategoryIndicatorComponentView.componentPosition 指示器的位置 預設:Bottom
JXCategoryIndicatorComponentView.scrollEnabled 手勢滾動、點選切換的時候,是否允許滾動,預設YES
JXCategoryIndicatorLineView.lineStyle 普通、京東、愛奇藝效果 預設:Normal
JXCategoryIndicatorLineView.lineScrollOffsetX 愛奇藝效果專用,line滾動時x的偏移量,預設為10;
JXCategoryIndicatorLineView.indicatorLineWidth 預設JXCategoryViewAutomaticDimension(與cellWidth相等)
JXCategoryIndicatorLineView.indicatorLineViewHeight 預設:3
JXCategoryIndicatorLineView.indicatorLineViewCornerRadius 預設JXCategoryViewAutomaticDimension (等於self.indicatorLineViewHeight/2)
JXCategoryIndicatorLineView.indicatorLineViewColor 預設為[UIColor redColor]
JXCategoryIndicatorTriangleView.triangleViewSize 預設:CGSizeMake(14, 10)
JXCategoryIndicatorTriangleView.triangleViewColor 預設為[UIColor redColor]
JXCategoryIndicatorImageView.indicatorImageView 設定image
JXCategoryIndicatorImageView.indicatorImageViewRollEnabled 是否允許滾動,預設:NO
JXCategoryIndicatorImageView.indicatorImageViewSize 預設:CGSizeMake(30, 20)
JXCategoryIndicatorBackgroundView.backgroundViewWidth 預設JXCategoryViewAutomaticDimension(與cellWidth相等)
JXCategoryIndicatorBackgroundView.backgroundViewWidthIncrement 寬度增量補償,因為backgroundEllipseLayer一般會比實際內容大一些。預設10
JXCategoryIndicatorBackgroundView.backgroundViewHeight 預設JXCategoryViewAutomaticDimension(與cell高度相等)
JXCategoryIndicatorBackgroundView.backgroundViewCornerRadius 預設JXCategoryViewAutomaticDimension(即backgroundViewHeight/2)
JXCategoryIndicatorBackgroundView.backgroundViewColor 預設為[UIColor redColor]
JXCategoryIndicatorBallView.ballViewSize 預設:CGSizeMake(15, 15)
JXCategoryIndicatorBallView.ballScrollOffsetX 小紅點的偏移量 預設:20
JXCategoryIndicatorBallView.ballViewColor 預設為[UIColor redColor]

可以多個IndicatorView搭配使用,但是效果需要自己把控,效果不是越多越好。參考混合使用;

使用

//1、初始化JXCategoryTitleView
self.categoryView = [[JXCategoryTitleView alloc] initWithFrame:CGRectMake(0, 0, WindowsSize.width, categoryViewHeight)];
self.categoryView.delegate = self;

//2、新增並配置指示器
//lineView
JXCategoryIndicatorLineView *lineView = [[JXCategoryIndicatorLineView alloc] init];
lineView.indicatorLineViewColor = [UIColor redColor];
lineView.indicatorLineWidth = JXCategoryViewAutomaticDimension;
//backgroundView
JXCategoryIndicatorBackgroundView *backgroundView = [[JXCategoryIndicatorBackgroundView alloc] init];
backgroundView.backgroundViewColor = [UIColor redColor];
backgroundView.backgroundViewWidth = JXCategoryViewAutomaticDimension;
titleCategoryView.indicators = @[lineView, backgroundView];

//3、繫結contentScrollView。self.scrollView的初始化細節參考原始碼。
self.categoryView.contentScrollView = self.scrollView;
[self.view addSubview:self.categoryView];
複製程式碼
  • 單個cell重新整理:比如紅點示例裡面,呼叫- (void)reloadCell:(NSUInteger)index
  • 所有狀態重置:資料來源、屬性配置有變動時(比如從伺服器拉取回來資料),需要呼叫reloadData方法重新整理狀態。

指示器樣式自定義

倉庫自帶:JXCategoryIndicatorLineView、JXCategoryIndicatorTriangleView、JXCategoryIndicatorImageView、JXCategoryIndicatorBackgroundView、JXCategoryIndicatorBallView

主要實現的方法:

  • 繼承JXCategoryIndicatorComponentView,內部遵從了JXCategoryIndicatorProtocol協議;
  • 實現協議方法,自定義效果:
    • - (void)jx_refreshState:(CGRect)selectedCellFrame初始化或reloadData,重置狀態;
    • - (void)jx_contentScrollViewDidScrollWithLeftCellFrame:(CGRect)leftCellFrame rightCellFrame:(CGRect)rightCellFrame selectedPosition:(JXCategoryCellClickedPosition)selectedPosition percent:(CGFloat)percent contentScrollView在進行手勢滑動時,處理指示器跟隨手勢變化UI邏輯;
    • - (void)jx_selectedCell:(CGRect)cellFrame clickedRelativePosition:(JXCategoryCellClickedPosition)clickedRelativePosition根據選中的某個cell,處理過渡效果;

具體例項:參考demo工程裡面的JXCategoryIndicatorDotLineView

Cell子類化注意事項

倉庫自帶:JXCategoryTitleView、JXCategoryTitleImageView、JXCategoryNumberView、JXCategoryDotView、JXCategoryImageView

主要實現的方法:

  • - (Class)preferredCellClass返回自定義的cell;
  • - (void)refreshDataSource重新整理資料來源,使用自定義的cellModel;
  • - (void)refreshCellModel:(JXCategoryBaseCellModel *)cellModel index:(NSInteger)index初始化、reloadData時對資料來源重置;
  • - (CGFloat)preferredCellWidthAtIndex:(NSInteger)index根據cell的內容返回對應的寬度;
  • - (void)refreshSelectedCellModel:(JXCategoryBaseCellModel *)selectedCellModel unselectedCellModel:(JXCategoryBaseCellModel *)unselectedCellModelcell選中時進行狀態重新整理;
  • - (void)refreshLeftCellModel:(JXCategoryBaseCellModel *)leftCellModel rightCellModel:(JXCategoryBaseCellModel *)rightCellModel ratio:(CGFloat)ratiocell左右滾動切換的時候,進行狀態重新整理;

具體例項:參考demo工程裡面的JXCategoryTitleAttributeView

繼承提示

  • 任何子類化,view、cell、cellModel三個都要子類化,即使某個子類cell什麼事情都不做。用於維護繼承鏈,以免以後子類化都不知道要繼承誰了;
  • 如果你想完全自定義cell裡面的內容,那就繼承JXCategoryIndicatorView、JXCategoryIndicatorCell、JXCategoryIndicatorCellModel,就像JXCategoryTitleView、JXCategoryTitleCell、JXCategoryTitleCellModel那樣去做;
  • 如果你只是在父類進行一些微調,那就繼承目標view、cell、cellModel,對cell原有控制元件微調、或者加入新的控制元件皆可。就像JXCategoryTitleImageView系列、JXCategoryTitleAttributeView系列那樣去做;

側滑手勢

首先,在viewDidAppear加上下面程式碼:

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    self.navigationController.interactivePopGestureRecognizer.enabled = (self.categoryView.selectedIndex == 0);
}
複製程式碼

系統預設返回Item

  • 點選處理:
#pragma mark - JXCategoryViewDelegate
- (void)categoryView:(JXCategoryBaseView *)categoryView didSelectedItemAtIndex:(NSInteger)index {
    self.navigationController.interactivePopGestureRecognizer.enabled = (index == 0);
}
複製程式碼

自定義導航欄返回Item

  • 設定代理:self.navigationController.interactivePopGestureRecognizer.delegate = (id)self;
  • 實現代理方法:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
    return YES;
}
複製程式碼
  • 點選處理:
#pragma mark - JXCategoryViewDelegate
- (void)categoryView:(JXCategoryBaseView *)categoryView didSelectedItemAtIndex:(NSInteger)index {
    self.navigationController.interactivePopGestureRecognizer.enabled = (index == 0);
}
複製程式碼

contentScrollView

  • 佈局靈活:JXCategoryView沒有與contentScrollView強關聯,你甚至可以不設定這個屬性,把它當做簡單的SegmentedControl。他們之間佈局沒有任何要求,可以把JXCategoryView放入導航欄、UITableViewSectionHeader等任何你想要的地方。
  • 點選處理:因為充分解耦,在JXCategoryView點選回撥中,你需要新增如下程式碼進行內容滾動切換:
#pragma mark - JXCategoryViewDelegate
- (void)categoryView:(JXCategoryBaseView *)categoryView didSelectedItemAtIndex:(NSInteger)index {
    [self.scrollView setContentOffset:CGPointMake(self.scrollView.bounds.size.width*index, 0) animated:YES];
}
複製程式碼

補充

該倉庫保持隨時更新,對於主流新的分類選擇效果會第一時間支援。使用過程中,有任何建議或問題,可以通過以下方式聯絡我: 郵箱:317437084@qq.com QQ群: 112440151

Github地址

下載原始碼,一睹為快!JXCategoryView

相關文章