這個(gè)效果我們經(jīng)常會(huì)看到比如外賣(mài),電商App的分類(lèi)頁(yè)面上看到铛楣,大概就是這樣:
點(diǎn)擊左側(cè)列表右側(cè)會(huì)跳到指定位置刀荒,滑動(dòng)右側(cè)左側(cè)會(huì)跟著切換,就是這么個(gè)東西窄陡。
然后常見(jiàn)的交互效果有兩種炕淮。一種是像“餓了嗎”點(diǎn)餐那種,右側(cè)是一體的可以一直滑動(dòng)跳夭。第二種是像“網(wǎng)易嚴(yán)選”分類(lèi)那樣涂圆,右側(cè)多個(gè)列表们镜,然后使用pagingEnabled效果進(jìn)行切換的。感興趣的可以看看這兩種润歉。然后我這次做了一個(gè)在第二種上進(jìn)行優(yōu)化的效果模狭,算是第三種吧。下面我們就說(shuō)說(shuō)這三個(gè)效果都是怎么做的踩衩。
第一種
左側(cè)列表沒(méi)什么好說(shuō)的就是一個(gè)列表嚼鹉,使用table和Collection都是可以的(我是比較習(xí)慣使用Collection)。右側(cè)由于也是連貫滑動(dòng)的驱富,所以也使用一個(gè)Collection就可以了锚赤。數(shù)據(jù)上看,一般都是返回的一個(gè)對(duì)象集合褐鸥,集合里每個(gè)對(duì)象還有個(gè)子分類(lèi)的幾個(gè):
"list": [{
"name": "大分類(lèi)"
"list": [{
"name": "小分類(lèi)",
"img": "https:\/\/res2.kongfz.com\/app\/search\/channel\/xianzhuang.png?2021122817"
}, {
"name": "小分類(lèi)",
"img": "https:\/\/res2.kongfz.com\/app\/search\/channel\/minguo.png?2021122817"
}]
},
{
"name": "大分類(lèi)"
"list": [{
"name": "小分類(lèi)",
"img": "https:\/\/res2.kongfz.com\/app\/search\/channel\/xianzhuang.png?2021122817"
}, {
"name": "小分類(lèi)",
"img": "https:\/\/res2.kongfz.com\/app\/search\/channel\/minguo.png?2021122817"
}]
}
]
這樣我們左側(cè)用外層的集合做數(shù)據(jù)线脚。右側(cè)根據(jù)兩層數(shù)據(jù)對(duì)列表進(jìn)行分組處理。外層對(duì)應(yīng)section里層對(duì)應(yīng)row叫榕。然后在點(diǎn)擊左側(cè)切換時(shí)跳轉(zhuǎn)到對(duì)應(yīng)的section浑侥,監(jiān)聽(tīng)右側(cè)滑動(dòng)的位置來(lái)刷新左側(cè)的選擇狀態(tài)就可以了。參考代碼如下:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
if (scrollView == _leftCollectionView ) {//如果是左側(cè)的直接返回
return;
}
//舉例這個(gè)每一個(gè)必有header翠霍,所以使用header判斷的锭吨,取最小是因?yàn)榕袛帱c(diǎn)在屏幕頂部
NSIndexPath *indexPath = [self getMinIndexPathForHeaderView];
if (!indexPath) { // 沒(méi)有header的情況
return;
}
KFZAuctionHeadCatModel *headerCatModel = [_categoryHomeModel.localCatList objectAtIndexCheck:indexPath.section];
KFZAuctionFirstCatModel *currentCatModel = [_categoryHomeModel.localContaniner objectForKey:headerCatModel.localSuperId];
if (currentCatModel.localSelected) {
return;
}
_categoryHomeModel.localCurrentCatModel.localSelected = NO;
currentCatModel.localSelected = YES;
_categoryHomeModel.localCurrentCatModel = currentCatModel;
[_leftCollectionView reloadData];
WS(ws)
[_leftCollectionView performBatchUpdates:nil completion:^(BOOL finished) {
NSInteger row = [ws.categoryHomeModel.localModelData indexOfObject:currentCatModel];
[ws.leftCollectionView scrollToItemAtIndexPath:[NSIndexPath indexPathForRow:row inSection:0] atScrollPosition: UICollectionViewScrollPositionCenteredVertically animated:YES];
}];
}
- (NSIndexPath *)getMinIndexPathForHeaderView{
NSIndexPath *targetIndexPath;
NSMutableArray *headerArray = [[_rightCollectionView indexPathsForVisibleSupplementaryElementsOfKind:UICollectionElementKindSectionHeader] mutableCopy];
if (headerArray.count > 0) {
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"section" ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:&sortDescriptor count:1];
[headerArray sortUsingDescriptors:sortDescriptors];
if (headerArray.count > 1) {
targetIndexPath = [headerArray firstObject];
} else {
NSIndexPath *indexPath = [headerArray firstObject];
UICollectionViewLayoutAttributes *attr = [_rightCollectionView.collectionViewLayout layoutAttributesForSupplementaryViewOfKind:UICollectionElementKindSectionHeader atIndexPath:indexPath];
CGRect endFrame = [self.view convertRect:attr.frame fromView:_rightCollectionView];
}
}
}
if (!targetIndexPath){
NSMutableArray *itemArray = [[_rightCollectionView indexPathsForVisibleItems] mutableCopy];
targetIndexPath = [itemArray firstObject];
}
return targetIndexPath;
}
第二種
左側(cè)和數(shù)據(jù)其實(shí)和第一種一樣。主要是右側(cè)的處理不同寒匙,以為要有分頁(yè)效果零如,右側(cè)用一個(gè)Collection就不行了,我這里使用的Collection套Collection的結(jié)構(gòu)(底層是一個(gè)Collection它的cell的大小是整個(gè)顯示區(qū)域然后里再放Collection)锄弱,這樣在底層左右兩個(gè)Collection是一一對(duì)應(yīng)的考蕾。外層多個(gè)小的Collection正常滑動(dòng)会宪,底層右側(cè)Collection設(shè)置pageing效果就可以了肖卧。
第三種(第二種優(yōu)化版)
還是先看效果:
頁(yè)面大體結(jié)構(gòu)和第二種是一樣的。優(yōu)化的點(diǎn):
1.右側(cè)paging是怎么切換的掸鹅,“網(wǎng)易嚴(yán)選”是劃不動(dòng)了然后切換塞帐,低層Collection是沒(méi)有滑動(dòng)能力的切換的觸發(fā)是靠外層做的像加載下一頁(yè)效果一樣。然后我這里是通過(guò)底層自身的滑動(dòng)去切換的好處就是手動(dòng)往下拉的時(shí)候能看到下面數(shù)據(jù)(正常是白色的)巍沙。
2.點(diǎn)擊左側(cè)切換葵姥,從上往下切換時(shí),下一個(gè)外層列表默認(rèn)在頂部句携;從下往上切換時(shí)下一個(gè)外層列表默認(rèn)在底部榔幸。代碼如下:
- (void)collectionView:(UICollectionView *)collectionView willDisplayCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath{
if (collectionView == self.rightCollectionView && collectionView.dragging) {
KFZCategoryHomeRightCell *rightCell = (KFZCategoryHomeRightCell *)cell;
if (indexPath.section >= self.selectIndex.section) {
[rightCell scrollToTop];
}else if (indexPath.section < self.selectIndex.section) {
[rightCell scrollToBottom];
}
}
}
3.有一部分樓層合并
gif上可以看出來(lái),我這個(gè)有一部分是連貫滑動(dòng)。做法上其實(shí)是在數(shù)據(jù)上就把需要連貫滑動(dòng)的數(shù)據(jù)合并到一起削咆,然后在通過(guò)代理把外層的刷新回傳到底層做的牍疏,具體有不少要處理的點(diǎn),這里就不一一說(shuō)了拨齐,我覺(jué)得正常用不到這個(gè)鳞陨,,奏黑,