我还真不知道该怎么介绍这一节所要给大家写的东西, 就感觉突然想写,就把他写下来了。 好了,先看一下效果图吧。
(这里我主要事项介绍一种思想,模仿苹果的思想.)

-
我主要想介绍的是,双排 tableView 的显示界面.以及关于自定义控件仿 tableView和代码扩展性的介绍.
1.1 闲话少说,要展示双排 tableView,自定义 view,xib 中加入两个 tableView 并添加约束
1.2 拖线,这里我们姑且将 view 称为 leftRightView, 左边的 tableView称为 leftTableView, 右边的 tableView 称为 rightTableView. 将左右两边的 tableView 的 dataSource (数据源)和 delegate(代理)都托给 leftRightView(其实在我看来这里的 leftRightView 就是一个容器 view, 就是为放东西的). -
现在是关键的时候,理解好的话,也许会对你的 tableView 有更深的印象.
2.1 我们之前说过要封装一个和 tableView 一样的控件,这样的我们就会想到, tableView 的数据和事件都是怎么处理的. 很简单,答案就是他们的数据源和代理提供和执行的.
2.2 那,我们就给自己的 leftRightView 书写数据源方法和代理方法,然后让成为我们数据源和代理的对象,给我提供数据,以及事件的处理.
2.3 大家就会想那内部怎么办呢, leftRightView 内部怎么办呢.
2.3.1 怎么办? 有数据的话,那数据个数不就知道了,有数据的话,展示什么的不就也知道了. 第二排得数据,是根据点击第一排数据的得到了.(想到了点击,就想到了代理方法了. )(给传入点击的行,返回数组数据, 有数据,再进行添加就行了).
3.也许大家还是不太明白, 在这里我讲方法书写一下,也许大家就会懂了.
3.1 数据源方法
// 数据源的方法
@class LXLLeftRightView;
@protocol LXLLeftRightViewDataSource<NSObject>
// 必须实现的方法
@required
/**
* 返回左边的 tableView 的数据个数
*
* @param leftRightView 模仿苹果将对象传入
*
* @return 数据个数.
*/
- (NSInteger)numberForItemsForleftRightView:(LXLLeftRightView *)leftRightView;
/**
* 返回左边每一行的 tableView 的展示文字
*
* @param leftRightView 模仿苹果将对象传入
* @param row 行号
*
* @return 返回字符串(文字)
*/
- (NSString *)leftRightView:(LXLLeftRightView *)leftRightView nameForRow:(NSInteger)row;
// 可选实现的方法
@optional
/**
* 返回左边每一行的 左边图片名字(看你模型中是否有这种属性)
*
* @param leftRightView 模仿苹果将对象传入
* @param row 行号
*
* @return 返回图片名字
*/
- (NSString *)leftRightView:(LXLLeftRightView *)leftRightView imageNameForRow:(NSInteger)row;
/**
* 返回左边每一行的 左边 cell 点击后的高亮图片(看你模型中是否有这一个属性)
*
* @param leftRightView 模仿苹果将对象传入
* @param row 行号
*
* @return 返回图片名字
*/
- (NSString *)leftRightView:(LXLLeftRightView *)leftRightView highLightImageNameForRow:(NSInteger)row;
@end
3.2 代理方法
// 代理方法
@protocol LXLLeftRightViewDelegate <NSObject>
@optional
/**
* 返回点击了左边leftTableView的某一行的 的数组数据,用于放置在右边rightTableView的 cell 种
*
* @param leftRightView 模仿苹果将对象传入
* @param row 行号
*
* @return 返回数组数据
*/
- (NSArray *)leftRightView:(LXLLeftRightView *)leftRightView didSelectRow:(NSInteger)row;
@end
3.3 先看看 leftRightView 内部是怎么给布置数据的
#pragma mark - 数据源方法
// 根据 tableView 的不同 ,来返回不同的行数.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (tableView == self.leftTableView) {
// 这里为什么不实现 [self.dataSoure respondsToSelector:<#(SEL)#>]方法,是因为这个方法是必须实现的,你要作我的数据源,就必须要实现我的方法
// 数据源执行方法,返回数据个数
return [self.dataSoure numberForItemsForleftRightView:self];
}else{
// 点击 左边 tableView 返回的数组数据(这里也是我原本模型中有的数据类型)
return self.subArray.count;
}
}
// 根据tableView 的不同,来展示 cell 的数据
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *ID = @"cell";
UITableViewCell *cell = nil;
// 这里我自定义了 cell, 当然你也可以自定义,或者 注册都可以的
if (tableView == self.leftTableView) {
cell = [LXLLeftRightCell leftRightCellWithtableView:tableView withReusableIdentifier:ID withStyle:UITableViewCellStyleDefault];
// 这里也是必须实现的方法, 用来返回左边 cell 的展示文字
cell.textLabel.text = [self.dataSoure leftRightView:self nameForRow:indexPath.row];
// 这里为可选方法,由于设定左边 cell 的显示图片和选中图片
if ([self.dataSoure respondsToSelector:@selector(leftRightView:imageNameForRow:)]) {
NSString *imageName = [self.dataSoure leftRightView:self imageNameForRow:indexPath.row];
cell.imageView.image = [UIImage imageNamed:imageName];
}
if ([self.dataSoure respondsToSelector:@selector(leftRightView:highLightImageNameForRow:)]) {
NSString *highLightImageName = [self.dataSoure leftRightView:self highLightImageNameForRow:indexPath.row];
cell.imageView.highlightedImage = [UIImage imageNamed:highLightImageName];
}
}else{
cell = [LXLLeftRightCell leftRightCellWithtableView:tableView withReusableIdentifier:ID withStyle:UITableViewCellStyleDefault];
// 根据返回的数组数据,给右边的 tableView 赋值
cell.textLabel.text = self.subArray[indexPath.row];
}
return cell ;
}
3.4 点击左边 cell 的 代理方法的实现
#pragma mark - 代理方法
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// 点击了左边 tableView 的 cell
if (tableView == self.leftTableView) {
// 如果实现了代理方法
if ([self.delegate respondsToSelector:@selector(leftRightView:didSelectRow:)]) {
// 返回一组数组(用于布置右边 tableView 的 显示)
self.subArray = [self.delegate leftRightView:self didSelectRow:indexPath.row];
// 刷新右边 tableView 的控件(如果不刷新,就不会显示. 因为数据源方法,不会执行,这里的刷新是用来强制执行数据源方法的)
[self.rightTableView reloadData];
}
}
}
4.如果大家看懂了上面几个方法的实现, 就会明白这个 leftRightView 就相当于一个 tableView, 我不需要知道数据具体是什么,只要设定了数据源对象,和代理对象,让他提供就行了. 这样的话,我的控件就独立出来了, 扩展性就加强了.
5.上面都懂了的话,我觉得下面的代码,就可以不用看了,跟废话基本没区别.(但还是写写把,即使是废话,也是很重要的)
5.1 先让能提供数据的控制器作为控件的数据源和代理(记得遵守协议哦)
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
LXLLeftRightView *categoryView = [LXLLeftRightView leftRightView];
categoryView.frame = self.view.bounds;
[self.view addSubview:categoryView];
categoryView.delegate = self;
categoryView.dataSoure = self;
}
5.2 实现对应的方法 (一般数据都是模型数组数据, 这里一般使用懒加载的方式,进行数据加载,主要是想提高启动效率,以为程序启动到显示,肯定要做很多事,如果你让他启动的时候就加载数据的话,是很耗性能,耗时也长的, 对于不好的手机,估计直接就死机了,O(∩_∩)O~).
// 数据加载, 这里我用的是 MJExtension 的框架,说真的很好用.但是前提你会模型转换才行,不要上手就用,而不动其中的运转机制
#pragma mark - 懒加载
- (NSArray *)categories
{
if (_categories == nil) {
_categories = [LXLCategory objectArrayWithFilename:@"categories.plist"];
}
return _categories;
}
#pragma mark - 数据源
// 返回左边 tableView 的行数
- (NSInteger)numberForItemsForleftRightView:(LXLLeftRightView *)leftRightView
{
return self.categories.count;
}
// 根据行号,取出模型,再返回模型中的 name 属性文字
- (NSString *)leftRightView:(LXLLeftRightView *)leftRightView nameForRow:(NSInteger)row
{
LXLCategory *category = self.categories[row];
return category.name;
}
// 根据行号取出模型,返回图片 name
- (NSString *)leftRightView:(LXLLeftRightView *)leftRightView imageNameForRow:(NSInteger)row
{
LXLCategory *category = self.categories[row];
return category.small_icon;
}
// 根据行号取出模型,返回高亮图片 name
- (NSString *)leftRightView:(LXLLeftRightView *)leftRightView highLightImageNameForRow:(NSInteger)row
{
LXLCategory *category = self.categories[row];
return category.small_highlighted_icon;
}
#pragma mark - 代理方法
// 根据选中的行号,返回 数组(模型中有的),用来布置右边的 tableView
- (NSArray *)leftRightView:(LXLLeftRightView *)leftRightView didSelectRow:(NSInteger)row
{
LXLCategory *category = self.categories[row];
return category.subcategories;
}
网友评论