我還真不知道該怎么介紹這一節(jié)所要給大家寫的東西蚯嫌, 就感覺突然想寫,就把他寫下來了丙躏。 好了择示,先看一下效果圖吧。
(這里我主要事項介紹一種思想,模仿蘋果的思想.)
我主要想介紹的是,雙排 tableView 的顯示界面.以及關(guān)于自定義控件仿 tableView和代碼擴展性的介紹.
1.1 閑話少說,要展示雙排 tableView,自定義 view,xib 中加入兩個 tableView 并添加約束
1.2 拖線,這里我們姑且將 view 稱為 leftRightView, 左邊的 tableView稱為 leftTableView, 右邊的 tableView 稱為 rightTableView. 將左右兩邊的 tableView 的 dataSource (數(shù)據(jù)源)和 delegate(代理)都托給 leftRightView(其實在我看來這里的 leftRightView 就是一個容器 view, 就是為放東西的).現(xiàn)在是關(guān)鍵的時候,理解好的話,也許會對你的 tableView 有更深的印象.
2.1 我們之前說過要封裝一個和 tableView 一樣的控件,這樣的我們就會想到, tableView 的數(shù)據(jù)和事件都是怎么處理的. 很簡單,答案就是他們的數(shù)據(jù)源和代理提供和執(zhí)行的.
2.2 那,我們就給自己的 leftRightView 書寫數(shù)據(jù)源方法和代理方法,然后讓成為我們數(shù)據(jù)源和代理的對象,給我提供數(shù)據(jù),以及事件的處理.
2.3 大家就會想那內(nèi)部怎么辦呢, leftRightView 內(nèi)部怎么辦呢.
2.3.1 怎么辦? 有數(shù)據(jù)的話,那數(shù)據(jù)個數(shù)不就知道了,有數(shù)據(jù)的話,展示什么的不就也知道了. 第二排得數(shù)據(jù),是根據(jù)點擊第一排數(shù)據(jù)的得到了.(想到了點擊,就想到了代理方法了. )(給傳入點擊的行,返回數(shù)組數(shù)據(jù), 有數(shù)據(jù),再進行添加就行了).
3.也許大家還是不太明白, 在這里我講方法書寫一下,也許大家就會懂了.
3.1 數(shù)據(jù)源方法
// 數(shù)據(jù)源的方法
@class LXLLeftRightView;
@protocol LXLLeftRightViewDataSource<NSObject>
// 必須實現(xiàn)的方法
@required
/**
* 返回左邊的 tableView 的數(shù)據(jù)個數(shù)
*
* @param leftRightView 模仿蘋果將對象傳入
*
* @return 數(shù)據(jù)個數(shù).
*/
- (NSInteger)numberForItemsForleftRightView:(LXLLeftRightView *)leftRightView;
/**
* 返回左邊每一行的 tableView 的展示文字
*
* @param leftRightView 模仿蘋果將對象傳入
* @param row 行號
*
* @return 返回字符串(文字)
*/
- (NSString *)leftRightView:(LXLLeftRightView *)leftRightView nameForRow:(NSInteger)row;
// 可選實現(xiàn)的方法
@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的某一行的 的數(shù)組數(shù)據(jù),用于放置在右邊rightTableView的 cell 種
*
* @param leftRightView 模仿蘋果將對象傳入
* @param row 行號
*
* @return 返回數(shù)組數(shù)據(jù)
*/
- (NSArray *)leftRightView:(LXLLeftRightView *)leftRightView didSelectRow:(NSInteger)row;
@end
3.3 先看看 leftRightView 內(nèi)部是怎么給布置數(shù)據(jù)的
#pragma mark - 數(shù)據(jù)源方法
// 根據(jù) tableView 的不同 ,來返回不同的行數(shù).
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (tableView == self.leftTableView) {
// 這里為什么不實現(xiàn) [self.dataSoure respondsToSelector:<#(SEL)#>]方法,是因為這個方法是必須實現(xiàn)的,你要作我的數(shù)據(jù)源,就必須要實現(xiàn)我的方法
// 數(shù)據(jù)源執(zhí)行方法,返回數(shù)據(jù)個數(shù)
return [self.dataSoure numberForItemsForleftRightView:self];
}else{
// 點擊 左邊 tableView 返回的數(shù)組數(shù)據(jù)(這里也是我原本模型中有的數(shù)據(jù)類型)
return self.subArray.count;
}
}
// 根據(jù)tableView 的不同,來展示 cell 的數(shù)據(jù)
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *ID = @"cell";
UITableViewCell *cell = nil;
// 這里我自定義了 cell, 當(dāng)然你也可以自定義,或者 注冊都可以的
if (tableView == self.leftTableView) {
cell = [LXLLeftRightCell leftRightCellWithtableView:tableView withReusableIdentifier:ID withStyle:UITableViewCellStyleDefault];
// 這里也是必須實現(xiàn)的方法, 用來返回左邊 cell 的展示文字
cell.textLabel.text = [self.dataSoure leftRightView:self nameForRow:indexPath.row];
// 這里為可選方法,由于設(shè)定左邊 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];
// 根據(jù)返回的數(shù)組數(shù)據(jù),給右邊的 tableView 賦值
cell.textLabel.text = self.subArray[indexPath.row];
}
return cell ;
}
3.4 點擊左邊 cell 的 代理方法的實現(xiàn)
#pragma mark - 代理方法
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// 點擊了左邊 tableView 的 cell
if (tableView == self.leftTableView) {
// 如果實現(xiàn)了代理方法
if ([self.delegate respondsToSelector:@selector(leftRightView:didSelectRow:)]) {
// 返回一組數(shù)組(用于布置右邊 tableView 的 顯示)
self.subArray = [self.delegate leftRightView:self didSelectRow:indexPath.row];
// 刷新右邊 tableView 的控件(如果不刷新,就不會顯示. 因為數(shù)據(jù)源方法,不會執(zhí)行,這里的刷新是用來強制執(zhí)行數(shù)據(jù)源方法的)
[self.rightTableView reloadData];
}
}
}
4.如果大家看懂了上面幾個方法的實現(xiàn), 就會明白這個 leftRightView 就相當(dāng)于一個 tableView, 我不需要知道數(shù)據(jù)具體是什么,只要設(shè)定了數(shù)據(jù)源對象,和代理對象,讓他提供就行了. 這樣的話,我的控件就獨立出來了, 擴展性就加強了.
5.上面都懂了的話,我覺得下面的代碼,就可以不用看了,跟廢話基本沒區(qū)別.(但還是寫寫把,即使是廢話,也是很重要的)
5.1 先讓能提供數(shù)據(jù)的控制器作為控件的數(shù)據(jù)源和代理(記得遵守協(xié)議哦)
- (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 實現(xiàn)對應(yīng)的方法 (一般數(shù)據(jù)都是模型數(shù)組數(shù)據(jù), 這里一般使用懶加載的方式,進行數(shù)據(jù)加載,主要是想提高啟動效率,以為程序啟動到顯示,肯定要做很多事,如果你讓他啟動的時候就加載數(shù)據(jù)的話,是很耗性能,耗時也長的, 對于不好的手機,估計直接就死機了,O(∩_∩)O~).
// 數(shù)據(jù)加載, 這里我用的是 MJExtension 的框架,說真的很好用.但是前提你會模型轉(zhuǎn)換才行,不要上手就用,而不動其中的運轉(zhuǎn)機制
#pragma mark - 懶加載
- (NSArray *)categories
{
if (_categories == nil) {
_categories = [LXLCategory objectArrayWithFilename:@"categories.plist"];
}
return _categories;
}
#pragma mark - 數(shù)據(jù)源
// 返回左邊 tableView 的行數(shù)
- (NSInteger)numberForItemsForleftRightView:(LXLLeftRightView *)leftRightView
{
return self.categories.count;
}
// 根據(jù)行號,取出模型,再返回模型中的 name 屬性文字
- (NSString *)leftRightView:(LXLLeftRightView *)leftRightView nameForRow:(NSInteger)row
{
LXLCategory *category = self.categories[row];
return category.name;
}
// 根據(jù)行號取出模型,返回圖片 name
- (NSString *)leftRightView:(LXLLeftRightView *)leftRightView imageNameForRow:(NSInteger)row
{
LXLCategory *category = self.categories[row];
return category.small_icon;
}
// 根據(jù)行號取出模型,返回高亮圖片 name
- (NSString *)leftRightView:(LXLLeftRightView *)leftRightView highLightImageNameForRow:(NSInteger)row
{
LXLCategory *category = self.categories[row];
return category.small_highlighted_icon;
}
#pragma mark - 代理方法
// 根據(jù)選中的行號,返回 數(shù)組(模型中有的),用來布置右邊的 tableView
- (NSArray *)leftRightView:(LXLLeftRightView *)leftRightView didSelectRow:(NSInteger)row
{
LXLCategory *category = self.categories[row];
return category.subcategories;
}