1、UITableViewDataSource數(shù)據(jù)源方法
// 返回第section組中有多少行
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;
// 返回多少組,沒實(shí)現(xiàn)該方法,默認(rèn)為1
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView;
2、UITableViewDelegate代理方法
// 即將顯示tableviewcell時(shí)調(diào)用
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath;
// 即將顯示header時(shí)調(diào)用账劲,在cell之后調(diào)用
- (void)tableView:(UITableView *)tableView willDisplayHeaderView:(UIView *)view forSection:(NSInteger)section NS_AVAILABLE_IOS(6_0);
// 即將顯示footer時(shí)調(diào)用戳护,在header之后調(diào)用
- (void)tableView:(UITableView *)tableView willDisplayFooterView:(UIView *)view forSection:(NSInteger)section NS_AVAILABLE_IOS(6_0);
// 在刪除cell之后調(diào)用金抡,停止顯示cell的時(shí)候調(diào)用,界面不顯示cell時(shí)瀑焦。
- (void)tableView:(UITableView *)tableView didEndDisplayingCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath*)indexPath NS_AVAILABLE_IOS(6_0);
// 停止顯示header的時(shí)候調(diào)用
- (void)tableView:(UITableView *)tableView didEndDisplayingHeaderView:(UIView *)view forSection:(NSInteger)section NS_AVAILABLE_IOS(6_0);
// 停止顯示footer的時(shí)候調(diào)用
- (void)tableView:(UITableView *)tableView didEndDisplayingFooterView:(UIView *)view forSection:(NSInteger)section NS_AVAILABLE_IOS(6_0);
3、高度代理方法
// 在設(shè)置每行cell的高度梗肝,header的高度榛瓮,footer的高度
// 設(shè)置某行cell高度
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;
// 設(shè)置header高度
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section;
// 設(shè)置footer高度
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section;
4、設(shè)置分組View的方法
// 返回某個(gè)section對應(yīng)的header標(biāo)題
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section;
// 返回某個(gè)section對應(yīng)的footer標(biāo)題
- (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section;
// 設(shè)置第section分組的header
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section;
// 設(shè)置第section分組的footer
- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section;
5巫击、操作cell時(shí)調(diào)用的方法
// cell選中時(shí)調(diào)用
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath;
// cell取消選中時(shí)調(diào)用
- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(3_0);
6禀晓、編輯模式相關(guān)的代理方法
// 返回每一行cell的編輯模式, 可以再次設(shè)置add或者刪除操作坝锰。
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath;
// cell左滑刪除時(shí)粹懒,刪除按鈕的標(biāo)題
- (NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(3_0);
// 自定義編輯左滑后出現(xiàn)的界面。 不止只有一個(gè)delete按鈕顷级, 可以自行定義凫乖,返回一個(gè)數(shù)組。數(shù)組中放著UITableviewRowAction
- (NSArray *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(8_0);
// 未實(shí)現(xiàn) 默認(rèn)為yes,進(jìn)入編輯時(shí)弓颈,cell是否縮進(jìn)帽芽。 在開啟編輯狀態(tài)時(shí)調(diào)用。
- (BOOL)tableView:(UITableView *)tableView shouldIndentWhileEditingRowAtIndexPath:(NSIndexPath *)indexPath;
// 右滑準(zhǔn)備進(jìn)行編輯的時(shí)候 調(diào)用翔冀。 將setediting = yes時(shí)不調(diào)用
- (void)tableView:(UITableView*)tableView willBeginEditingRowAtIndexPath:(NSIndexPath *)indexPath;
// 完成編輯的時(shí)候調(diào)用
- (void)tableView:(UITableView*)tableView didEndEditingRowAtIndexPath:(NSIndexPath *)indexPath;
6导街、索引
//返回要顯示的section索引標(biāo)題
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView;
// return list of section titles to display in section index view (e.g. "ABCD...Z#")
// 點(diǎn)擊右側(cè)索引表項(xiàng)時(shí)調(diào)用
- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index;
// 返回指定點(diǎn)所在位置的indexPath
- (NSIndexPath *)indexPathForRowAtPoint:(CGPoint)point;
// 返回指定cell所在的indexPath
- (NSIndexPath *)indexPathForCell:(UITableViewCell *)cell;
// 返回指定范圍rect中的所有cell的indexPath
- (NSArray *)indexPathsForRowsInRect:(CGRect)rect; // returns nil if rect not valid
// 返回索引indexPath所指向的cell。
- (UITableViewCell *)cellForRowAtIndexPath:(NSIndexPath *)indexPath;
7纤子、UITableView的屬性和構(gòu)造方法
// cell的構(gòu)造方法,自定義cell時(shí),如果要初始化設(shè)置cell屬性時(shí),可以重寫該方法,在方法內(nèi)部設(shè)置
- (instancetype)initWithFrame:(CGRect)frame style:(UITableViewStyle)style;
// UITableView的類型: plain類型和group分組類型
@property (nonatomic, readonly) UITableViewStyle style;
// 數(shù)據(jù)源
@property (nonatomic, assign) id <UITableViewDataSource> dataSource;
// 代理
@property (nonatomic, assign) id <UITableViewDelegate> delegate;
// 設(shè)置所有cell的行高,默認(rèn)44
@property (nonatomic) CGFloat rowHeight;
// 分組頭部高度
@property (nonatomic) CGFloat sectionHeaderHeight;
// 分組尾部高度
@property (nonatomic) CGFloat sectionFooterHeight;
// cell估算高度,默認(rèn)0
@property (nonatomic) CGFloat estimatedRowHeight NS_AVAILABLE_IOS(7_0);
// 分組頭部估算高度
@property (nonatomic) CGFloat estimatedSectionHeaderHeight NS_AVAILABLE_IOS(7_0);
// 分組微博估算高度
@property (nonatomic) CGFloat estimatedSectionFooterHeight NS_AVAILABLE_IOS(7_0);
// 分割線內(nèi)邊距
@property (nonatomic) UIEdgeInsets separatorInset NS_AVAILABLE_IOS(7_0) UI_APPEARANCE_SELECTOR; // allows customization of the frame of cell separators
8搬瑰、cell刷新方法
// 重新載入tableview所有cell 一般是在數(shù)據(jù)源有改變的時(shí)候
- (void)reloadData;
// 重新載入,section的索引標(biāo)題控硼。
- (void)reloadSectionIndexTitles NS_AVAILABLE_IOS(3_0); // reloads the index bar.
8跌捆、UITableView滾動(dòng)方法
// 根據(jù)傳入的indexPath,滾動(dòng)到相對應(yīng)的位置象颖,第二個(gè)參數(shù)是控制對應(yīng)的cell再滾動(dòng)后處于tableview的頂部/底部/中部等
- (void)scrollToRowAtIndexPath:(NSIndexPath *)indexPath atScrollPosition:(UITableViewScrollPosition)scrollPosition animated:(BOOL)animated;
// 滾動(dòng)到被選中項(xiàng)佩厚。 滾動(dòng)后處于tableview的頂部/底部/中部等
- (void)scrollToNearestSelectedRowAtScrollPosition:(UITableViewScrollPosition)scrollPosition animated:(BOOL)animated;
9、插入,刪除,刷新,移動(dòng)section組
// 插入,刪除,刷新,移動(dòng)section組
// 插入section
- (void)insertSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation;
// 刪除section
- (void)deleteSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation;
// 刷新section
- (void)reloadSections:(NSIndexSet *)sections withRowAnimation:
(UITableViewRowAnimation)animation NS_AVAILABLE_IOS(3_0);
// 移動(dòng)section
- (void)moveSection:(NSInteger)section toSection:(NSInteger)newSection NS_AVAILABLE_IOS(5_0);
實(shí)戰(zhàn)演習(xí)
1说订、多選
在結(jié)算購物車的時(shí)候抄瓦,我們需要選中多組cell,我們往往都是寫了很多代碼陶冷,很是麻煩钙姊,其實(shí)tableView有一個(gè)自帶屬性:刪除多個(gè)Cell,這個(gè)時(shí)候我們可以稍作修改埂伦,就可以做成我們想要的購物車了,十分簡單.
效果圖:
注意點(diǎn):
1煞额、[_tableView setEditing:YES animated:YES];//設(shè)為為編輯狀態(tài),不然不會(huì)出現(xiàn)左側(cè)圓圈
2、設(shè)置編輯狀態(tài)的代理膊毁。
編輯狀態(tài)UITableViewCellEditingStyle有三種模式
UITableViewCellEditingStyleDelete
UITableViewCellEditingStyleInsert
UITableViewCellEditingStyleNone
多選框的風(fēng)格, 只需要風(fēng)格同時(shí)包含UITableViewCellEditingStyleDelete和UITableViewCellEditingStyleInsert就可以了
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath{
return UITableViewCellEditingStyleDelete | UITableViewCellEditingStyleInsert;
}
3胀莹、選中是會(huì)出現(xiàn)藍(lán)色背景,要是感覺不好看婚温,可以修改
cell.multipleSelectionBackgroundView = [UIView new];
4描焰、修改有點(diǎn)擊選中圖標(biāo)的顏色
cell.tintColor = [UIColor redColor];
5、不想使用默認(rèn)圖標(biāo)的話栅螟,也可以在自定義
-(void)layoutSubviews
{
for (UIControl *control in self.subviews){
if ([control isMemberOfClass:NSClassFromString(@"UITableViewCellEditControl")]){
for (UIView *v in control.subviews)
{
if ([v isKindOfClass: [UIImageView class]]) {
UIImageView *img=(UIImageView *)v;
if (self.selected) {
img.image=[UIImage imageNamed:@"xuanzhong_icon"];
}else
{
img.image=[UIImage imageNamed:@"weixuanzhong_icon"];
}
}
}
}
}
[super layoutSubviews];
}
//適配第一次圖片為空的情況
- (void)setEditing:(BOOL)editing animated:(BOOL)animated
{
[super setEditing:editing animated:animated];
for (UIControl *control in self.subviews){
if ([control isMemberOfClass:NSClassFromString(@"UITableViewCellEditControl")]){
for (UIView *v in control.subviews)
{
if ([v isKindOfClass: [UIImageView class]]) {
UIImageView *img=(UIImageView *)v;
if (!self.selected) {
img.image=[UIImage imageNamed:@"weixuanzhong_icon"];
}
}
}
}
}
}
6荆秦、第一次點(diǎn)擊選中,第二次點(diǎn)擊刪除
//已經(jīng)選中了某一行
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if ([_selectArray containsObject:_dataSource[indexPath.row]]) {
return;
}
[_selectArray addObject:_dataSource[indexPath.row]];
}
//不選的時(shí)候刪除
- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath
{
[_selectArray removeObject:indexPath];
}
7力图、全選選中與清空
- (void)SelectButton:(UIButton*)button{
button.selected = !button.selected;
if (button.selected) {
//==================全選================
//選中tableView中所有的indexPath
NSArray * array = [_tableView indexPathsForRowsInRect:CGRectMake(0, 0, SCREEN_WIDTH, _tableView.contentSize.height)];
for (NSIndexPath * indexPath in array) {
[_tableView selectRowAtIndexPath:indexPath animated:YES scrollPosition:UITableViewScrollPositionNone];
}
[_selectArray removeAllObjects];
[_selectArray addObjectsFromArray:_dataSource];
}else{
//============全選清空====================
for (NSIndexPath * indexPath in _selectArray) {
[_tableView deselectRowAtIndexPath:indexPath animated:YES];
}
//將選中下標(biāo)數(shù)組清空
[_selectArray removeAllObjects];
[_tableView reloadData];
}
}
2步绸、索引
tableView 自帶有索引條,要是項(xiàng)目對索引沒有太大的要求吃媒,可以直接使用tableView自帶的索引靡努。當(dāng)我們需要一些特定的索引條的時(shí)候,我們可以自定制晓折,自定制思路:1惑朦、在屏幕滾動(dòng)查看當(dāng)前屏幕中最上面出現(xiàn)的是哪一組,屏幕滾動(dòng)的時(shí)候有一個(gè)代理漓概。2漾月、找到最上面出現(xiàn)的是哪一組。
我們可以根據(jù)情況定制索引條胃珍。這里我只是介紹一下自帶索引梁肿。
效果圖
設(shè)置索引欄,常要用的一些方法
//設(shè)置索引欄
//背景色設(shè)置
_tableView.sectionIndexBackgroundColor = [UIColor grayColor];
//索引顏色
_tableView.sectionIndexColor = [UIColor redColor];
//點(diǎn)中時(shí)背景色
_tableView.sectionIndexTrackingBackgroundColor = [UIColor blueColor];
需要遵守的代理方法
#pragma mark - 索引欄顯示
- (NSArray<NSString *> *)sectionIndexTitlesForTableView:(UITableView *)tableView
{
//需要將每一組的title拿出來存放到數(shù)組中并且返回
NSMutableArray * array = [[NSMutableArray alloc] init];
for (JJHCarGroup * carGroup in _dataSource) {
[array addObject:carGroup.title];
}
[array insertObject:@"#" atIndex:0];
return array;
}
- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index
{
//默認(rèn)返回的是index,如果標(biāo)題前面有其它東西觅彰,比如聯(lián)系人列表最前面有個(gè)#號吩蔑,需要返回index-1,否則和預(yù)期的不匹配填抬。
return index - 1;
}
3烛芬、搜索欄
UISearchBar 是蘋果自帶的原生搜索框,簡單好用飒责,如果沒有什么特殊的需求赘娄,我們完全可以使用這個(gè)搜索框
效果圖
1、初始化:UISearchBar繼承于UIView宏蛉,我們可以像創(chuàng)建View那樣創(chuàng)建searchBar
UISearchBar * bar = [[UISearchBar alloc]initWithFrame:CGRectMake(20, 100, 250, 40)];
[self.view addSubview:bar];
2遣臼、這個(gè)屬性可以設(shè)置searchBar的搜索框的風(fēng)格,枚舉如下
@property(nonatomic) UIBarStyle barStyle;
typedef NS_ENUM(NSInteger, UIBarStyle) {
UIBarStyleDefault = 0,//默認(rèn)風(fēng)格 白色搜索框拾并,多出的背景為灰色
UIBarStyleBlack = 1,//黑色風(fēng)格揍堰,黑色的搜索框
//下面兩個(gè)枚舉已經(jīng)被禁用鹏浅,作用和黑色風(fēng)格一樣
UIBarStyleBlackOpaque = 1, // Deprecated. Use UIBarStyleBlack
UIBarStyleBlackTranslucent = 2, // Deprecated. Use UIBarStyleBlack and set the translucent property to YES
};
3、UISearchBar常用屬性
// 自適應(yīng)大小
[searchBar sizeToFit];
// 1.設(shè)置搜索框的樣式
[searchBar setBarStyle:UIBarStyleDefault];
// 2.設(shè)置背景圖片(該方法可以去掉UISearchBar上下的兩條線)
searchBar.backgroundImage = [UIImage imageNamed:@"search_bg_icon"];
// 3.設(shè)置主題顏色
searchBar.barTintColor = [UIColor redColor];
// 4.設(shè)置外邊框顏色
searchBar.barTintColor = [UIColor greenColor];
// 5.設(shè)置光標(biāo)顏色
searchBar.tintColor = [UIColor cyanColor];
// 6.設(shè)置是否透明
searchBar.translucent = YES;
// 7.設(shè)置占位文字
searchBar.placeholder = @"占位文字";
// 8.輸入框中間的提示文字
searchBar.prompt = @"提示文字";
// 9.顯示搜索框右側(cè)的搜索結(jié)果按鈕
searchBar.showsSearchResultsButton = YES;
// 10.搜索框右側(cè)的搜索結(jié)果按鈕是否選中
searchBar.searchResultsButtonSelected = YES;
// 11.設(shè)置UISearchBar背景的偏移量
searchBar.searchFieldBackgroundPositionAdjustment = UIOffsetMake(50, 20);
// 12.設(shè)置UISearchBar開始編輯時(shí)文本的偏移量
searchBar.searchTextPositionAdjustment = UIOffsetMake(50, 20);
// 13.開始編輯時(shí)鍵盤上方出現(xiàn)一個(gè)遮蓋視圖
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 0, 266)];
view.backgroundColor = [UIColor yellowColor];
searchBar.inputAccessoryView = view;
// 14.設(shè)置鍵盤的樣式
searchBar.keyboardType = UIKeyboardTypeASCIICapable;
// 15.是否顯示搜索框下面的選項(xiàng)條
searchBar.showsScopeBar = YES;
// 16.搜索框下面選項(xiàng)條中選項(xiàng)的名稱
searchBar.scopeButtonTitles = @[@"aaaa",@"bbbb",@"cccc"];
// 17.選項(xiàng)條的背景圖片
searchBar.scopeBarBackgroundImage = [UIImage imageNamed:@"ios_v4_preview_2"];
// 18.選項(xiàng)條默認(rèn)選中的按鈕下標(biāo)
searchBar.selectedScopeButtonIndex = 1;
// 19.顯示輸入框右側(cè)的書形圖標(biāo)
searchBar.showsBookmarkButton = YES;
// 20.顯示右側(cè)的取消按鈕(無動(dòng)畫)
// searchBar.showsCancelButton = YES;
// 21.顯示右側(cè)的取消按鈕(有動(dòng)畫)
[searchBar setShowsCancelButton:YES animated:YES];
4屏歹、UISearchBar的代理方法
// 開始編輯時(shí)會(huì)來到該方法
- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar
// 結(jié)束編輯時(shí)會(huì)來到該方法
- (void)searchBarTextDidEndEditing:(UISearchBar *)searchBar
// 開始編輯時(shí)會(huì)來到該方法(可以在該方法判斷是否允許用戶輸入)
- (BOOL)searchBarShouldBeginEditing:(UISearchBar *)searchBar
// 結(jié)束編輯時(shí)會(huì)來到該方法
- (BOOL)searchBarShouldEndEditing:(UISearchBar *)searchBar
// 點(diǎn)擊取消按鈕時(shí)會(huì)來到該方法
- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar
// 點(diǎn)擊鍵盤的搜索按鈕時(shí)會(huì)來到該方法
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar
// 輸入框內(nèi)容發(fā)生改變時(shí),會(huì)來到該方法
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
5隐砸、簡單項(xiàng)目代碼
@interface ViewController6 () <UISearchResultsUpdating>
/**
* 搜索控制器
*/
@property (nonatomic) UISearchController * searchController;
/**
* 搜索結(jié)果存放數(shù)組
*/
@property (nonatomic) NSMutableArray * searchResultsArray;
@end
@implementation LZBViewController6
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
self.searchResultsArray = [[NSMutableArray alloc] init];
[self createSearchController];
}
- (void)createSearchController
{
//創(chuàng)建搜索控制器。參數(shù)寫nil代表使用當(dāng)前控制器的view來顯示搜索結(jié)果
self.searchController = [[UISearchController alloc] initWithSearchResultsController:nil];
//設(shè)置搜索結(jié)果更新代理西采,實(shí)現(xiàn)協(xié)議中方法,更新搜索結(jié)果
self.searchController.searchResultsUpdater = self;
//兩個(gè)屬性設(shè)置
//顯示搜索結(jié)果時(shí)是否添加半透明覆蓋層 默認(rèn)YES
self.searchController.dimsBackgroundDuringPresentation = NO;
//搜索的時(shí)候是否隱藏導(dǎo)航欄 默認(rèn)YES
self.searchController.hidesNavigationBarDuringPresentation = NO;
//設(shè)置搜索欄顯示到tableView頭部視圖上面
self.tableView.tableHeaderView = self.searchController.searchBar;
}
#pragma mark - 搜索更新結(jié)果方法實(shí)現(xiàn)
- (void)updateSearchResultsForSearchController:(UISearchController *)searchController
{
//取出搜索欄里面的內(nèi)容
NSString * text = searchController.searchBar.text;
NSArray * array = [self.dataModel searchWithText:text];
self.searchResultsArray.array = array;
//讓tableView重新刷新數(shù)據(jù)
[self.tableView reloadData];
}
#pragma mark - 因?yàn)槭褂玫氖峭粋€(gè)表格視圖继控,所以需要重寫表格視圖所有方法
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
//判斷當(dāng)前搜索控制器是否處在活動(dòng)狀態(tài)
if (self.searchController.isActive) {
return 1;
}
return [super numberOfSectionsInTableView:tableView];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (self.searchController.isActive) {
return self.searchResultsArray.count;
}
return [super tableView:tableView numberOfRowsInSection:section];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (self.searchController.isActive) {
//取出一個(gè)空閑cell械馆,將里面的內(nèi)容改變
UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];
cell.textLabel.text = self.searchResultsArray[indexPath.row];
return cell;
}
return [super tableView:tableView cellForRowAtIndexPath:indexPath];
}
4、左右聯(lián)動(dòng)
效果圖
實(shí)現(xiàn) tableView聯(lián)動(dòng) 主要分兩種狀況(需要?jiǎng)?chuàng)建兩個(gè)tableView)
1武通、點(diǎn)擊 左側(cè) cell 讓右側(cè) tableView 滾到對應(yīng)位置
//MARK: - 點(diǎn)擊 cell 的代理方法
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// 判斷是否為 左側(cè) 的 tableView
if (tableView == self.leftTableView) {
// 計(jì)算出 右側(cè) tableView 將要 滾動(dòng)的 位置
NSIndexPath *moveToIndexPath = [NSIndexPath indexPathForRow:0 inSection:indexPath.row];
// 將 rightTableView 移動(dòng)到對應(yīng)的 位置
[self.rightTableView scrollToRowAtIndexPath:moveToIndexPath atScrollPosition:UITableViewScrollPositionTop animated:YES];
}
}
2霹崎、滑動(dòng) 右側(cè) tableView 讓左側(cè) tableView 滾到對應(yīng)位置
[self.rightTableView indexPathsForVisibleRows] 返回 所有顯示在界面的 cell 的 indexPath
//MARK: - 一個(gè)方法就能搞定 右邊滑動(dòng)時(shí)跟左邊的聯(lián)動(dòng)
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
// 如果是 左側(cè)的 tableView 直接return
if (scrollView == self.leftTableView) return;
// 取出顯示在 視圖 且最靠上 的 cell 的 indexPath
NSIndexPath *topHeaderViewIndexpath = [[self.rightTableView indexPathsForVisibleRows] firstObject];
// 左側(cè) talbelView 移動(dòng)到的位置 indexPath
NSIndexPath *moveToIndexpath = [NSIndexPath indexPathForRow:topHeaderViewIndexpath.section inSection:0];
// 移動(dòng) 左側(cè) tableView 到 指定 indexPath 居中顯示
[self.leftTableView selectRowAtIndexPath:moveToIndexpath animated:YES scrollPosition:UITableViewScrollPositionMiddle];
}
代碼:
#import "ViewController.h"
#import "food.h"
#import "foodGroup.h"
#import "LeftTableViewCell.h"
#import "RightTableViewCell.h"
#import "UIImageView+WebCache.h"
#define leftTableWidth [UIScreen mainScreen].bounds.size.width * 0.3
#define rightTableWidth [UIScreen mainScreen].bounds.size.width * 0.7
#define ScreenWidth [UIScreen mainScreen].bounds.size.width
#define ScreenHeight [UIScreen mainScreen].bounds.size.height
#define leftCellIdentifier @"leftCellIdentifier"
#define rightCellIdentifier @"rightCellIdentifier"
@interface ViewController ()<UITableViewDataSource, UITableViewDelegate>
{
//數(shù)據(jù)源
NSMutableArray *_dataSource;
}
@property (nonatomic, weak) UITableView *leftTableView;
@property (nonatomic, weak) UITableView *rightTableView;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
_dataSource = [[NSMutableArray alloc]init];
[self.view addSubview:_leftTableView];
[self.view addSubview:_rightTableView];
[self createleftTableView];
[self createRightTableView];
//獲取數(shù)據(jù)源
[self getDataSource];
}
- (void)createleftTableView{
UITableView *tableView = [[UITableView alloc]initWithFrame:CGRectMake(0, 64, leftTableWidth, ScreenHeight-64)];
[self.view addSubview:tableView];
_leftTableView = tableView;
tableView.delegate = self;
tableView.dataSource = self;
[tableView registerClass:[LeftTableViewCell class] forCellReuseIdentifier:leftCellIdentifier];
}
- (void)createRightTableView{
UITableView *tableView = [[UITableView alloc] initWithFrame:CGRectMake(leftTableWidth, 64, rightTableWidth, ScreenHeight-64)];
[self.view addSubview:tableView];
_rightTableView = tableView;
tableView.delegate = self;
tableView.dataSource = self;
_rightTableView.rowHeight = 80;
[tableView registerNib:[UINib nibWithNibName:@"RightTableViewCell" bundle:nil] forCellReuseIdentifier:rightCellIdentifier];
}
//獲取數(shù)據(jù)源
- (void)getDataSource{
NSString *path = [[NSBundle mainBundle] pathForResource:@"meituan" ofType:@"json"];
NSData *data = [NSData dataWithContentsOfFile:path];
NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil];
NSArray *foodGroups = dict[@"data"][@"food_spu_tags"];
for (NSDictionary *foodGroupsDic in foodGroups) {
foodGroup *MyGroup = [[foodGroup alloc]init];
MyGroup.name = foodGroupsDic[@"name"];
NSArray * foodArray = foodGroupsDic[@"spus"];
for (NSDictionary *foodDic in foodArray) {
food *MyFood = [[food alloc]init];
MyFood.name = foodDic[@"name"];
MyFood.ImageURL = foodDic[@"picture"];
MyFood.month_saled_content = foodDic[@"month_saled_content"];
[MyGroup.foodArray addObject:MyFood];
}
[_dataSource addObject:MyGroup];
}
[_leftTableView reloadData];
[_rightTableView reloadData];
}
#pragma mark - 數(shù)據(jù)源
//返回指定的組數(shù),如果是多組,必須實(shí)現(xiàn)這個(gè)方法冶忱,返回指定組數(shù)尾菇,如果是一組,這個(gè)方法可以不實(shí)現(xiàn)囚枪,默認(rèn)是一組
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
if (tableView == _leftTableView) {
return 1;
}
return _dataSource.count;
}
//返回指定組的行數(shù)
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (tableView == _leftTableView) {
return _dataSource.count;
}else{
foodGroup *Group = _dataSource[section];
return Group.foodArray.count;
}
}
- (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
if (tableView == _leftTableView) {
//左邊cell
LeftTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:leftCellIdentifier forIndexPath:indexPath];
foodGroup *Group = _dataSource[indexPath.row];
cell.textLabel.text = Group.name;
cell.textLabel.adjustsFontSizeToFitWidth = YES;
return cell;
}else{
//右邊cell
RightTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:rightCellIdentifier forIndexPath:indexPath];
foodGroup *Group = _dataSource[indexPath.section];
food *MyFood = Group.foodArray[indexPath.row];
cell.foodNameLabel.text = MyFood.name;
cell.xiaoLiangLAbel.text = MyFood.month_saled_content;
[cell.MYHeadImageView sd_setImageWithURL:[NSURL URLWithString:MyFood.ImageURL]];
return cell;
}
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section{
if (tableView == _rightTableView) {
foodGroup *Group = _dataSource[section];
return Group.name;
}else{
return nil;
}
}
#pragma mark - 滑動(dòng) 右側(cè) tableView 讓左側(cè) tableView 滾到對應(yīng)位置
//MARK: - 一個(gè)方法就能搞定 右邊滑動(dòng)時(shí)跟左邊的聯(lián)動(dòng)
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
// 如果是 左側(cè)的 tableView 直接return
if (scrollView == self.leftTableView) return;
// 取出顯示在 視圖 且最靠上 的 cell 的 indexPath
NSIndexPath *topHeaderViewIndexpath = [[self.rightTableView indexPathsForVisibleRows] firstObject];
// 左側(cè) talbelView 移動(dòng)的 indexPath
NSIndexPath *moveToIndexpath = [NSIndexPath indexPathForRow:topHeaderViewIndexpath.section inSection:0];
// 移動(dòng) 左側(cè) tableView 到 指定 indexPath 居中顯示
[self.leftTableView selectRowAtIndexPath:moveToIndexpath animated:YES scrollPosition:UITableViewScrollPositionMiddle];
}
//MARK: - 點(diǎn)擊右側(cè) cell 的代理方法
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// 選中 左側(cè) 的 tableView
if (tableView == self.leftTableView) {
NSIndexPath *moveToIndexPath = [NSIndexPath indexPathForRow:0 inSection:indexPath.row];
// 將右側(cè) tableView 移動(dòng)到指定位置
[self.rightTableView selectRowAtIndexPath:moveToIndexPath animated:YES scrollPosition:UITableViewScrollPositionTop];
// 取消選中效果
[self.rightTableView deselectRowAtIndexPath:moveToIndexPath animated:YES];
}
}
@end
5派诬、分組的展開收起
效果圖
定義一個(gè)section對象,保存一個(gè)isExpand標(biāo)識來判斷展開與收起狀態(tài)链沼。點(diǎn)擊的時(shí)候設(shè)置下isExpand默赂,然后reload下就行了。
核心代碼
- (NSInteget)cellForRowAtIndexPath:(NSIndexPath)indexPath{
if(section.isExpand){
return dataSource[indexPath.section].count;
} else {
return 0;
}
}
完整代碼
- (void)loadData {
if (!self.dataArray) {
self.dataArray = [NSMutableArray array];
}
if (!self.isExpland) {
self.isExpland = [NSMutableArray array];
}
//這里用一個(gè)二維數(shù)組來模擬數(shù)據(jù)括勺。
self.dataArray = [NSArray arrayWithObjects:@[@"a",@"b",@"c",@"d"],@[@"d",@"e",@"f"],@[@"h",@"i",@"j",@"m",@"n"],nil].mutableCopy;
//用0代表收起缆八,非0(不一定是1)代表展開,默認(rèn)都是收起的
for (int i = 0; i < self.dataArray.count; i++) {
[self.isExpland addObject:@0];
}
[self.tableView reloadData];
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return self.dataArray.count;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
//這里是關(guān)鍵疾捍,如果選中
NSArray *array = self.dataArray[section];
if ([self.isExpland[section] boolValue]) {
return array.count;
}
else {
return 0;
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell" forIndexPath:indexPath];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:@"cell"];
}
cell.textLabel.text = self.dataArray[indexPath.section][indexPath.row];
return cell;
}
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
UIButton *headerSection = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, kScreenWidth, 44)];
headerSection.tag = 666+section;
//標(biāo)題
[headerSection setTitle:[NSString stringWithFormat:@"第%@組",@(section)] forState:UIControlStateNormal];
[headerSection addTarget:self action:@selector(buttonAction:) forControlEvents:UIControlEventTouchUpInside];
return headerSection;
}
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
return 44;
}
- (void)buttonAction:(UIButton *)button {
NSInteger section = button.tag - 666;
self.isExpland[section] = [self.isExpland[section] isEqual:@0]?@1:@0;
NSIndexSet *set = [NSIndexSet indexSetWithIndex:section];
[self.tableView reloadSections:set withRowAnimation:UITableViewRowAnimationFade];
}