仿半糖效果,又和半糖效果有些區(qū)別
效果展示:
對比
半糖效果:
第一個頁面 banner 隱藏之后揩悄,滑動到其它界面丈积,滑動至 banner 顯示時,其它界面會重置回頂部位置惠拭。
AGPageControllerViewController:
第一個頁面 banner 隱藏之后扩劝,滑動到其它界面,滑動至 banner 顯示時职辅,不會影響到之前界面的滑動位置棒呛,界面位置保持在原來的位置。
優(yōu)點(diǎn)
1域携,簡單易用
通過繼承 AGPageControllerViewController
即可使用簇秒。對于每個子控制器的顯示,由每個子控制器自己負(fù)責(zé)即可秀鞭。
2趋观,自定義標(biāo)簽欄樣式
標(biāo)簽欄使用 collectionView 實(shí)現(xiàn),提供了默認(rèn)的樣式锋边。開發(fā)者也可以根據(jù)自己的需求拆内,重寫標(biāo)簽欄 cell 的樣式(具體查看 AGPageControllerViewController .h
#pragma mark - 自定義標(biāo)簽設(shè)置 下提供的方法)。
缺點(diǎn)及待解決的問題:
1宠默,banner 顯示時滑動麸恍,有底部的 tableView 有跳動
在真機(jī)上,效果比較不錯,在模擬器和7p大屏幕的手機(jī)上抹沪,界面的跳動可以被觀察到刻肄。由于界面需要保持自己原有的位置,因此需要實(shí)時的記錄滾動時的位置融欧,這導(dǎo)致 banner 顯示時的滾動中敏弃,可以看到界面會有一些跳動。
2噪馏,設(shè)置默認(rèn)選中頁時麦到,能夠看到切換過程
由于使用的是 collectionView 來實(shí)現(xiàn)上面的標(biāo)簽欄,collectionView 中的 cell 沒有載入完成時欠肾,設(shè)置其滾動到指點(diǎn)的 cell 是無效的瓶颠。
現(xiàn)在的處理方式:
通過延時等待 collectionView 的 cell 載入完畢后在滾動
3,- (void)setContentOffset:(CGPoint)contentOffset animated:(BOOL)animated;
方法的問題
標(biāo)簽切換的過程中涉及到滾動的位置問題刺桃,如果設(shè)置滾動的時候粹淋,設(shè)置 animated 為 YES,滾動的位置就會發(fā)生偏差瑟慈。
AGPageControllerViewController
提供了界面滾動會頂部的 方法 - (void)allViewScrollToTop;
桃移,也會出現(xiàn)同樣的問題。
現(xiàn)在的處理方法:
將 animated 設(shè)置為NO葛碧,但是在切換的過程中借杰,界面沒有滾動的過程,一下就切換過去了
文件結(jié)構(gòu)
使用:
工程地址:
https://github.com/againxu/AGCustomPageControllerView.git
里面包含了具體的使用方法
一进泼,繼承 AGPageControllerViewController
使用第步。
@interface ViewController1 : AGPageControllerViewController
使用提供的初始化方法 - (instancetype)initWithChildControllers:(NSArray<UIViewController *> *)ag_childControllers;
進(jìn)行設(shè)置
// 創(chuàng)建要顯示的子控制器
NSMutableArray *childVcs = [NSMutableArray array];
for (int index = 0; index < 10; index++) {
if (index % 2) {
TableViewController *tabVc = [[TableViewController alloc] init];
tabVc.title = [NSString stringWithFormat:@"==== %d ====", index];
[childVcs addObject:tabVc];
}else{
CollectionViewController *collVc = [[CollectionViewController alloc] init];
collVc.title = [NSString stringWithFormat:@"== %d ==", index];
[childVcs addObject:collVc];
}
}
ViewController1 *vc = [[ViewController1 alloc] initWithChildControllers:childVcs];
AGPageControllerViewController
中提供了具體配置方法,可以根據(jù)具體的需要來實(shí)現(xiàn)需求:
// 頭部視圖是否允許滾動
@property (nonatomic, assign) BOOL scrollEnable;
/** 設(shè)置子控件(滾動標(biāo)簽和自控制是否彈性效果) */
@property (nonatomic, assign) BOOL subViewsbounces;
/** 滾動標(biāo)簽樣式 */
@property (nonatomic, assign) AGLabelAlignment labelAlignment;
/** 標(biāo)簽選中的樣式 */
@property (nonatomic, assign) AGSelectStyle selectStyle;
/** 設(shè)置當(dāng)前標(biāo)簽位置 */
- (void)setCurrentLabelIndex:(NSInteger)index;
/** 頭視圖 */
- (UIView *)tableHeaderView;
/** 標(biāo)簽欄高度 */
- (CGFloat)heightOfscrollLabelControl;
/** 重寫:?自定義滑動條上的視圖 */
//- (UIView *)viewForSectionHeader;
/** 滾動條右側(cè)視圖:默認(rèn)無 */
- (UIView *)rightViewForSectionHeader;
/** 更新頭部視圖:tableViewHeader 如果是動態(tài)設(shè)定的缘琅,可以使用此方法更新 */
- (void)reloadTableViewHeader;
/** 更新子控制器 */
- (void)updateChildContollers:(NSArray<UIViewController *> *)childControllers;
- (void)reloadPageControlChildControllers;
/** 所有視圖滾動到頂部 */
- (void)allViewScrollToTop;
#pragma mark - 自定義標(biāo)簽設(shè)置
/** 注冊自定義類型的 標(biāo)簽 */
/** 這是個代理方法粘都,如果需要注冊自定義的 lable cell,實(shí)現(xiàn)代理進(jìn)行注冊 */
- (void)registerCellForScrollLabel:(AGScrollLabelView *)scrollLabelView;
/** 自定義類型標(biāo)簽 */
- (UICollectionViewCell *)scrollLabel:(AGScrollLabelView *)scrollLabelView collectionView:(UICollectionView *)collectionView cellforIndexPath:(NSIndexPath *)indexPath;
/** 標(biāo)簽個數(shù)刷袍,如果只顯示title(通過設(shè)置vc.titles即可)翩隧,不需要實(shí)現(xiàn)這里的方法 */
- (NSInteger)numberOfItemsInScrollLabelView:(AGScrollLabelView *)scrollLabelView;
/** 自定義類型標(biāo)簽的size */
- (CGSize)scrollLabel:(AGScrollLabelView *)scrollLabelView sizeForCellAtIndexPath:(NSIndexPath *)indexPath;
/** 當(dāng)前選中的 標(biāo)簽 */
- (void)scrollLabelScrollCell:(UICollectionViewCell *)cell atIndex:(NSInteger)index;
二,自定義標(biāo)簽欄標(biāo)簽樣式
在繼承 AGPageControllerViewController
的子類中重寫下面的方法呻纹。方法的使用和 collectionView 的數(shù)據(jù)源方法一樣堆生,具體見 demo
/** 注冊自定義類型的 標(biāo)簽 */
/** 這是個代理方法,如果需要注冊自定義的 lable cell雷酪,實(shí)現(xiàn)代理進(jìn)行注冊 */
- (void)registerCellForScrollLabel:(AGScrollLabelView *)scrollLabelView;
/** 自定義類型標(biāo)簽 */
- (UICollectionViewCell *)scrollLabel:(AGScrollLabelView *)scrollLabelView collectionView:(UICollectionView *)collectionView cellforIndexPath:(NSIndexPath *)indexPath;
/** 標(biāo)簽個數(shù)淑仆,如果只顯示title(通過設(shè)置vc.titles即可),不需要實(shí)現(xiàn)這里的方法 */
- (NSInteger)numberOfItemsInScrollLabelView:(AGScrollLabelView *)scrollLabelView;
/** 自定義類型標(biāo)簽的size */
- (CGSize)scrollLabel:(AGScrollLabelView *)scrollLabelView sizeForCellAtIndexPath:(NSIndexPath *)indexPath;
對自定義標(biāo)簽的選中樣式進(jìn)行設(shè)置
在自定義的 cell 中實(shí)現(xiàn)如下方法哥力,并進(jìn)行樣式的設(shè)定即可
/** 設(shè)置選中狀態(tài)的樣式 */
- (void)setSelected:(BOOL)selected{
[super setSelected:selected];
if (selected) {
self.label.textColor = [UIColor redColor];
}
else{
self.label.textColor = [UIColor whiteColor];
}
}
細(xì)節(jié)處理:
1蔗怠,子控制器 viewDidLoad 觸發(fā)實(shí)際控制
子控制器是添加在 collectionView 的 cell 上墩弯,cell 會預(yù)先加載視圖,因此如果在 - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
方法中直接添加控制器的 view 寞射,有些控制器的 view 在 cell 沒有顯示出來時就已經(jīng)添加到 cell 上了渔工。
處理:
a,- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
處理已經(jīng)顯示過的控制器視圖桥温,如果沒有顯示過引矩,不通過該方法顯示
b,滑動過程中視圖的添加侵浸,通過判斷滑動結(jié)束時旺韭,在 cell 上添加控制器的 view ,并進(jìn)行標(biāo)記
/** 用來保存顯示過的視圖控制器的下標(biāo)掏觉,默認(rèn)包含下標(biāo) 0区端,通過 `- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath ` 方法添加 */
_didLoadViewIndex = @[@0].mutableCopy;
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView{
if ([self.delegate respondsToSelector:@selector(containerCollectionViewController:scrollAtIndex:currentContentController:)]) {
NSInteger index = scrollView.contentOffset.x / CGRectGetWidth(self.collectionView.frame);
if (![self.didLoadViewIndex containsObject:@(index)]) {
[self.didLoadViewIndex addObject:@(index)];
UICollectionViewCell *cell = [self.collectionView cellForItemAtIndexPath:[NSIndexPath indexPathForRow:index inSection:0]];
UIViewController *vc = self.ag_childControllers[index];
vc.view.frame = self.frame;
[cell.contentView.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];
[cell.contentView addSubview:vc.view];
}
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:reuseIdentifier forIndexPath:indexPath];
[cell.contentView.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];
if ([self.didLoadViewIndex containsObject:@(indexPath.row)]) {
UIViewController *vc = self.ag_childControllers[indexPath.row];
vc.view.frame = self.frame;
[cell.contentView addSubview:vc.view];
}
return cell;
}
使用中遇到的問題處理:
1,tableView的上拉獲取數(shù)據(jù)刷新履腋,如果出現(xiàn)界面跳動珊燎,判斷獲取的數(shù)據(jù)是否為空惭嚣,為空則tableView不reloaData
if (data.count) {
[self.tableView reloadData];
}
對于項(xiàng)目中的存在的問題遵湖,如果有好的解決方案,希望能夠提出來晚吞,一起討論討論