1、UITableViewDataSource数据源方法
// 返回第section组中有多少行
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;
// 返回多少组,没实现该方法,默认为1
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView;
2、UITableViewDelegate代理方法
// 即将显示tableviewcell时调用
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath;
// 即将显示header时调用,在cell之后调用
- (void)tableView:(UITableView *)tableView willDisplayHeaderView:(UIView *)view forSection:(NSInteger)section NS_AVAILABLE_IOS(6_0);
// 即将显示footer时调用,在header之后调用
- (void)tableView:(UITableView *)tableView willDisplayFooterView:(UIView *)view forSection:(NSInteger)section NS_AVAILABLE_IOS(6_0);
// 在删除cell之后调用,停止显示cell的时候调用,界面不显示cell时。
- (void)tableView:(UITableView *)tableView didEndDisplayingCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath*)indexPath NS_AVAILABLE_IOS(6_0);
// 停止显示header的时候调用
- (void)tableView:(UITableView *)tableView didEndDisplayingHeaderView:(UIView *)view forSection:(NSInteger)section NS_AVAILABLE_IOS(6_0);
// 停止显示footer的时候调用
- (void)tableView:(UITableView *)tableView didEndDisplayingFooterView:(UIView *)view forSection:(NSInteger)section NS_AVAILABLE_IOS(6_0);
3、高度代理方法
// 在设置每行cell的高度,header的高度,footer的高度
// 设置某行cell高度
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;
// 设置header高度
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section;
// 设置footer高度
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section;
4、设置分组View的方法
// 返回某个section对应的header标题
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section;
// 返回某个section对应的footer标题
- (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section;
// 设置第section分组的header
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section;
// 设置第section分组的footer
- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section;
5、操作cell时调用的方法
// cell选中时调用
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath;
// cell取消选中时调用
- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(3_0);
6、编辑模式相关的代理方法
// 返回每一行cell的编辑模式, 可以再次设置add或者删除操作。
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath;
// cell左滑删除时,删除按钮的标题
- (NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(3_0);
// 自定义编辑左滑后出现的界面。 不止只有一个delete按钮, 可以自行定义,返回一个数组。数组中放着UITableviewRowAction
- (NSArray *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(8_0);
// 未实现 默认为yes,进入编辑时,cell是否缩进。 在开启编辑状态时调用。
- (BOOL)tableView:(UITableView *)tableView shouldIndentWhileEditingRowAtIndexPath:(NSIndexPath *)indexPath;
// 右滑准备进行编辑的时候 调用。 将setediting = yes时不调用
- (void)tableView:(UITableView*)tableView willBeginEditingRowAtIndexPath:(NSIndexPath *)indexPath;
// 完成编辑的时候调用
- (void)tableView:(UITableView*)tableView didEndEditingRowAtIndexPath:(NSIndexPath *)indexPath;
6、索引
//返回要显示的section索引标题
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView;
// return list of section titles to display in section index view (e.g. "ABCD...Z#")
// 点击右侧索引表项时调用
- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index;
// 返回指定点所在位置的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的属性和构造方法
// cell的构造方法,自定义cell时,如果要初始化设置cell属性时,可以重写该方法,在方法内部设置
- (instancetype)initWithFrame:(CGRect)frame style:(UITableViewStyle)style;
// UITableView的类型: plain类型和group分组类型
@property (nonatomic, readonly) UITableViewStyle style;
// 数据源
@property (nonatomic, assign) id <UITableViewDataSource> dataSource;
// 代理
@property (nonatomic, assign) id <UITableViewDelegate> delegate;
// 设置所有cell的行高,默认44
@property (nonatomic) CGFloat rowHeight;
// 分组头部高度
@property (nonatomic) CGFloat sectionHeaderHeight;
// 分组尾部高度
@property (nonatomic) CGFloat sectionFooterHeight;
// cell估算高度,默认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);
// 分割线内边距
@property (nonatomic) UIEdgeInsets separatorInset NS_AVAILABLE_IOS(7_0) UI_APPEARANCE_SELECTOR; // allows customization of the frame of cell separators
8、cell刷新方法
// 重新载入tableview所有cell 一般是在数据源有改变的时候
- (void)reloadData;
// 重新载入,section的索引标题。
- (void)reloadSectionIndexTitles NS_AVAILABLE_IOS(3_0); // reloads the index bar.
8、UITableView滚动方法
// 根据传入的indexPath,滚动到相对应的位置,第二个参数是控制对应的cell再滚动后处于tableview的顶部/底部/中部等
- (void)scrollToRowAtIndexPath:(NSIndexPath *)indexPath atScrollPosition:(UITableViewScrollPosition)scrollPosition animated:(BOOL)animated;
// 滚动到被选中项。 滚动后处于tableview的顶部/底部/中部等
- (void)scrollToNearestSelectedRowAtScrollPosition:(UITableViewScrollPosition)scrollPosition animated:(BOOL)animated;
9、插入,删除,刷新,移动section组
// 插入,删除,刷新,移动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);
// 移动section
- (void)moveSection:(NSInteger)section toSection:(NSInteger)newSection NS_AVAILABLE_IOS(5_0);
实战演习
1、多选
在结算购物车的时候,我们需要选中多组cell,我们往往都是写了很多代码,很是麻烦,其实tableView有一个自带属性:删除多个Cell,这个时候我们可以稍作修改,就可以做成我们想要的购物车了,十分简单.
效果图:
注意点:
1、[_tableView setEditing:YES animated:YES];//设为为编辑状态,不然不会出现左侧圆圈
2、设置编辑状态的代理。
编辑状态UITableViewCellEditingStyle有三种模式
UITableViewCellEditingStyleDelete
UITableViewCellEditingStyleInsert
UITableViewCellEditingStyleNone
多选框的风格, 只需要风格同时包含UITableViewCellEditingStyleDelete和UITableViewCellEditingStyleInsert就可以了
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath{
return UITableViewCellEditingStyleDelete | UITableViewCellEditingStyleInsert;
}
3、选中是会出现蓝色背景,要是感觉不好看,可以修改
cell.multipleSelectionBackgroundView = [UIView new];
4、修改有点击选中图标的颜色
cell.tintColor = [UIColor redColor];
5、不想使用默认图标的话,也可以在自定义
-(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、第一次点击选中,第二次点击删除
//已经选中了某一行
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if ([_selectArray containsObject:_dataSource[indexPath.row]]) {
return;
}
[_selectArray addObject:_dataSource[indexPath.row]];
}
//不选的时候删除
- (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];
}
//将选中下标数组清空
[_selectArray removeAllObjects];
[_tableView reloadData];
}
}
2、索引
tableView 自带有索引条,要是项目对索引没有太大的要求,可以直接使用tableView自带的索引。当我们需要一些特定的索引条的时候,我们可以自定制,自定制思路:1、在屏幕滚动查看当前屏幕中最上面出现的是哪一组,屏幕滚动的时候有一个代理。2、找到最上面出现的是哪一组。
我们可以根据情况定制索引条。这里我只是介绍一下自带索引。
效果图
设置索引栏,常要用的一些方法
//设置索引栏
//背景色设置
_tableView.sectionIndexBackgroundColor = [UIColor grayColor];
//索引颜色
_tableView.sectionIndexColor = [UIColor redColor];
//点中时背景色
_tableView.sectionIndexTrackingBackgroundColor = [UIColor blueColor];
需要遵守的代理方法
#pragma mark - 索引栏显示
- (NSArray<NSString *> *)sectionIndexTitlesForTableView:(UITableView *)tableView
{
//需要将每一组的title拿出来存放到数组中并且返回
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
{
//默认返回的是index,如果标题前面有其它东西,比如联系人列表最前面有个#号,需要返回index-1,否则和预期的不匹配。
return index - 1;
}
3、搜索栏
UISearchBar 是苹果自带的原生搜索框,简单好用,如果没有什么特殊的需求,我们完全可以使用这个搜索框
效果图
1、初始化:UISearchBar继承于UIView,我们可以像创建View那样创建searchBar
UISearchBar * bar = [[UISearchBar alloc]initWithFrame:CGRectMake(20, 100, 250, 40)];
[self.view addSubview:bar];
2、这个属性可以设置searchBar的搜索框的风格,枚举如下
@property(nonatomic) UIBarStyle barStyle;
typedef NS_ENUM(NSInteger, UIBarStyle) {
UIBarStyleDefault = 0,//默认风格 白色搜索框,多出的背景为灰色
UIBarStyleBlack = 1,//黑色风格,黑色的搜索框
//下面两个枚举已经被禁用,作用和黑色风格一样
UIBarStyleBlackOpaque = 1, // Deprecated. Use UIBarStyleBlack
UIBarStyleBlackTranslucent = 2, // Deprecated. Use UIBarStyleBlack and set the translucent property to YES
};
3、UISearchBar常用属性
// 自适应大小
[searchBar sizeToFit];
// 1.设置搜索框的样式
[searchBar setBarStyle:UIBarStyleDefault];
// 2.设置背景图片(该方法可以去掉UISearchBar上下的两条线)
searchBar.backgroundImage = [UIImage imageNamed:@"search_bg_icon"];
// 3.设置主题颜色
searchBar.barTintColor = [UIColor redColor];
// 4.设置外边框颜色
searchBar.barTintColor = [UIColor greenColor];
// 5.设置光标颜色
searchBar.tintColor = [UIColor cyanColor];
// 6.设置是否透明
searchBar.translucent = YES;
// 7.设置占位文字
searchBar.placeholder = @"占位文字";
// 8.输入框中间的提示文字
searchBar.prompt = @"提示文字";
// 9.显示搜索框右侧的搜索结果按钮
searchBar.showsSearchResultsButton = YES;
// 10.搜索框右侧的搜索结果按钮是否选中
searchBar.searchResultsButtonSelected = YES;
// 11.设置UISearchBar背景的偏移量
searchBar.searchFieldBackgroundPositionAdjustment = UIOffsetMake(50, 20);
// 12.设置UISearchBar开始编辑时文本的偏移量
searchBar.searchTextPositionAdjustment = UIOffsetMake(50, 20);
// 13.开始编辑时键盘上方出现一个遮盖视图
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 0, 266)];
view.backgroundColor = [UIColor yellowColor];
searchBar.inputAccessoryView = view;
// 14.设置键盘的样式
searchBar.keyboardType = UIKeyboardTypeASCIICapable;
// 15.是否显示搜索框下面的选项条
searchBar.showsScopeBar = YES;
// 16.搜索框下面选项条中选项的名称
searchBar.scopeButtonTitles = @[@"aaaa",@"bbbb",@"cccc"];
// 17.选项条的背景图片
searchBar.scopeBarBackgroundImage = [UIImage imageNamed:@"ios_v4_preview_2"];
// 18.选项条默认选中的按钮下标
searchBar.selectedScopeButtonIndex = 1;
// 19.显示输入框右侧的书形图标
searchBar.showsBookmarkButton = YES;
// 20.显示右侧的取消按钮(无动画)
// searchBar.showsCancelButton = YES;
// 21.显示右侧的取消按钮(有动画)
[searchBar setShowsCancelButton:YES animated:YES];
4、UISearchBar的代理方法
// 开始编辑时会来到该方法
- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar
// 结束编辑时会来到该方法
- (void)searchBarTextDidEndEditing:(UISearchBar *)searchBar
// 开始编辑时会来到该方法(可以在该方法判断是否允许用户输入)
- (BOOL)searchBarShouldBeginEditing:(UISearchBar *)searchBar
// 结束编辑时会来到该方法
- (BOOL)searchBarShouldEndEditing:(UISearchBar *)searchBar
// 点击取消按钮时会来到该方法
- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar
// 点击键盘的搜索按钮时会来到该方法
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar
// 输入框内容发生改变时,会来到该方法
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
5、简单项目代码
@interface ViewController6 () <UISearchResultsUpdating>
/**
* 搜索控制器
*/
@property (nonatomic) UISearchController * searchController;
/**
* 搜索结果存放数组
*/
@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
{
//创建搜索控制器。参数写nil代表使用当前控制器的view来显示搜索结果
self.searchController = [[UISearchController alloc] initWithSearchResultsController:nil];
//设置搜索结果更新代理,实现协议中方法,更新搜索结果
self.searchController.searchResultsUpdater = self;
//两个属性设置
//显示搜索结果时是否添加半透明覆盖层 默认YES
self.searchController.dimsBackgroundDuringPresentation = NO;
//搜索的时候是否隐藏导航栏 默认YES
self.searchController.hidesNavigationBarDuringPresentation = NO;
//设置搜索栏显示到tableView头部视图上面
self.tableView.tableHeaderView = self.searchController.searchBar;
}
#pragma mark - 搜索更新结果方法实现
- (void)updateSearchResultsForSearchController:(UISearchController *)searchController
{
//取出搜索栏里面的内容
NSString * text = searchController.searchBar.text;
NSArray * array = [self.dataModel searchWithText:text];
self.searchResultsArray.array = array;
//让tableView重新刷新数据
[self.tableView reloadData];
}
#pragma mark - 因为使用的是同一个表格视图,所以需要重写表格视图所有方法
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
//判断当前搜索控制器是否处在活动状态
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) {
//取出一个空闲cell,将里面的内容改变
UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];
cell.textLabel.text = self.searchResultsArray[indexPath.row];
return cell;
}
return [super tableView:tableView cellForRowAtIndexPath:indexPath];
}
4、左右联动
效果图
实现 tableView联动 主要分两种状况(需要创建两个tableView)
1、点击 左侧 cell 让右侧 tableView 滚到对应位置
//MARK: - 点击 cell 的代理方法
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// 判断是否为 左侧 的 tableView
if (tableView == self.leftTableView) {
// 计算出 右侧 tableView 将要 滚动的 位置
NSIndexPath *moveToIndexPath = [NSIndexPath indexPathForRow:0 inSection:indexPath.row];
// 将 rightTableView 移动到对应的 位置
[self.rightTableView scrollToRowAtIndexPath:moveToIndexPath atScrollPosition:UITableViewScrollPositionTop animated:YES];
}
}
2、滑动 右侧 tableView 让左侧 tableView 滚到对应位置
[self.rightTableView indexPathsForVisibleRows] 返回 所有显示在界面的 cell 的 indexPath
//MARK: - 一个方法就能搞定 右边滑动时跟左边的联动
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
// 如果是 左侧的 tableView 直接return
if (scrollView == self.leftTableView) return;
// 取出显示在 视图 且最靠上 的 cell 的 indexPath
NSIndexPath *topHeaderViewIndexpath = [[self.rightTableView indexPathsForVisibleRows] firstObject];
// 左侧 talbelView 移动到的位置 indexPath
NSIndexPath *moveToIndexpath = [NSIndexPath indexPathForRow:topHeaderViewIndexpath.section inSection:0];
// 移动 左侧 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>
{
//数据源
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];
//获取数据源
[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];
}
//获取数据源
- (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 - 数据源
//返回指定的组数,如果是多组,必须实现这个方法,返回指定组数,如果是一组,这个方法可以不实现,默认是一组
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
if (tableView == _leftTableView) {
return 1;
}
return _dataSource.count;
}
//返回指定组的行数
- (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 - 滑动 右侧 tableView 让左侧 tableView 滚到对应位置
//MARK: - 一个方法就能搞定 右边滑动时跟左边的联动
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
// 如果是 左侧的 tableView 直接return
if (scrollView == self.leftTableView) return;
// 取出显示在 视图 且最靠上 的 cell 的 indexPath
NSIndexPath *topHeaderViewIndexpath = [[self.rightTableView indexPathsForVisibleRows] firstObject];
// 左侧 talbelView 移动的 indexPath
NSIndexPath *moveToIndexpath = [NSIndexPath indexPathForRow:topHeaderViewIndexpath.section inSection:0];
// 移动 左侧 tableView 到 指定 indexPath 居中显示
[self.leftTableView selectRowAtIndexPath:moveToIndexpath animated:YES scrollPosition:UITableViewScrollPositionMiddle];
}
//MARK: - 点击右侧 cell 的代理方法
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// 选中 左侧 的 tableView
if (tableView == self.leftTableView) {
NSIndexPath *moveToIndexPath = [NSIndexPath indexPathForRow:0 inSection:indexPath.row];
// 将右侧 tableView 移动到指定位置
[self.rightTableView selectRowAtIndexPath:moveToIndexPath animated:YES scrollPosition:UITableViewScrollPositionTop];
// 取消选中效果
[self.rightTableView deselectRowAtIndexPath:moveToIndexPath animated:YES];
}
}
@end
5、分组的展开收起
效果图
定义一个section对象,保存一个isExpand标识来判断展开与收起状态。点击的时候设置下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];
}
//这里用一个二维数组来模拟数据。
self.dataArray = [NSArray arrayWithObjects:@[@"a",@"b",@"c",@"d"],@[@"d",@"e",@"f"],@[@"h",@"i",@"j",@"m",@"n"],nil].mutableCopy;
//用0代表收起,非0(不一定是1)代表展开,默认都是收起的
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 {
//这里是关键,如果选中
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;
//标题
[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];
}