實現選擇
網上大部分的教程,都是基于修改section的hearderView來實現的,但是看QQ的好友列表,style是grouped,顯然不是使用section的header來處理。使用section的hearderView來實現的,十分簡單,網上也有很多源碼和教程,只要刷新一下dataSource然后調用就可以了。不在本次討論的范圍之內。
- (void)reloadSections:(NSIndexSet *)sections
這次我直接使用grouped的cell來做父cell,點擊后展開相應的子cell,還有動畫特效。(目測QQ好友列表沒有使用動畫特效,可能是因為好友列表過于大,內存占用問題或者是用戶體驗問題。)
封裝測試數據
使用FMDB(或者CoreData)從objc中國獲取主issue作為父級cell,文章作為subCell,具體獲取使用python和BeautifulSoup,不在本次的討論范圍之內,需要的可以查看相應的資料或者留言我,也可以在文末的項目源碼里獲取python代碼。
具體實現分析
TableView一些相關方法介紹
delegate里和點擊有關的方法如下。
- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
- (NSIndexPath *)tableView:(UITableView *)tableView willDeselectRowAtIndexPath:(NSIndexPath *)indexPath
- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath
當有點擊事件發生時,運行順序為。
- willSelect
- willDeselect
- didDeselect
- didSelect
插入刪除cell的方法為
- (void)insertRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation
- (void)deleteRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation
記得把他們放在
[table beginUpdates];
//input insert/delete code here
[table endUpdates];
邏輯分析
在didSelect的時候執行插入代碼。
[tableView beginUpdates];
[tableView insertRowsAtIndexPaths:indexArray withRowAnimation:UITableViewRowAnimationTop];
[tableView endUpdates];
[tableView beginUpdates];
[tableView deleteRowsAtIndexPaths:indexArray withRowAnimation:UITableViewRowAnimationRight];
[tableView endUpdates];
其中的indexArray需要動態計算。類似這樣。
NSMutableArray* indexArray = [NSMutableArray array];
for (int i=1; i<=masterModel.subIuuses.count; i++) {
NSIndexPath* path = [NSIndexPath indexPathForRow:i+indexPath.row inSection:indexPath.section];
[indexArray addObject:path];
}
可以實現這樣的效果。
問題分析
看起來沒有什么問題。
但是當點擊的是展開的cell下方的cell時,indexPath就會出現問題。像下面這樣。
我要點擊的是2x,但是實際上點擊的卻是4x,問題出在哪里?看這個圖片就會發現問題,原來還是那幾個方法的執行順序問題。
在執行的時候,先執行didDeselect里面的代碼,導致插入的cell被刪除,indexPath變化,然后再didSelect,當然選中的不是我們想要選中的那個cell了。
解決方案
如下圖。
只要willSelect的時候return一個新的indexPath即可,這個indexPath通過計算得出。下面是我的willSelect里的實現代碼。
-(NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell* cell = [tableView cellForRowAtIndexPath:indexPath];
if (cell && [cell isMemberOfClass:[SIMMasterTableViewCell class]]) {
//點擊masterCell
if (_isShowIssues) {
//展開狀態
if(indexPath.row>_lastSelectMatserIndexPath.row)
return [NSIndexPath indexPathForRow:indexPath.row-_lastModelIssuesCount inSection:indexPath.section];
else
return indexPath;
}
return indexPath;
}
else if(cell)
{
_isSelectSubCell = YES;
return indexPath;
//點擊到uitableviewcell
}
return indexPath;
}
最后放上一張效果圖。