FLEXMultiColumnTableView.m 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. //
  2. // PTMultiColumnTableView.m
  3. // PTMultiColumnTableViewDemo
  4. //
  5. // Created by Peng Tao on 15/11/16.
  6. // Copyright © 2015年 Peng Tao. All rights reserved.
  7. //
  8. #import "FLEXMultiColumnTableView.h"
  9. #import "FLEXTableContentCell.h"
  10. #import "FLEXTableLeftCell.h"
  11. @interface FLEXMultiColumnTableView ()
  12. <UITableViewDataSource, UITableViewDelegate,UIScrollViewDelegate, FLEXTableContentCellDelegate>
  13. @property (nonatomic, strong) UIScrollView *contentScrollView;
  14. @property (nonatomic, strong) UIScrollView *headerScrollView;
  15. @property (nonatomic, strong) UITableView *leftTableView;
  16. @property (nonatomic, strong) UITableView *contentTableView;
  17. @property (nonatomic, strong) UIView *leftHeader;
  18. @property (nonatomic, strong) NSDictionary *sortStatusDict;
  19. @property (nonatomic, strong) NSArray *rowData;
  20. @end
  21. static const CGFloat kColumnMargin = 1;
  22. @implementation FLEXMultiColumnTableView
  23. - (instancetype)initWithFrame:(CGRect)frame
  24. {
  25. self = [super initWithFrame:frame];
  26. if (self) {
  27. [self loadUI];
  28. }
  29. return self;
  30. }
  31. - (void)didMoveToSuperview
  32. {
  33. [super didMoveToSuperview];
  34. [self reloadData];
  35. }
  36. - (void)layoutSubviews
  37. {
  38. [super layoutSubviews];
  39. CGFloat width = self.frame.size.width;
  40. CGFloat height = self.frame.size.height;
  41. CGFloat topheaderHeight = [self topHeaderHeight];
  42. CGFloat leftHeaderWidth = [self leftHeaderWidth];
  43. CGFloat contentWidth = 0.0;
  44. NSInteger rowsCount = [self numberOfColumns];
  45. for (int i = 0; i < rowsCount; i++) {
  46. contentWidth += [self contentWidthForColumn:i];
  47. }
  48. self.leftTableView.frame = CGRectMake(0, topheaderHeight, leftHeaderWidth, height - topheaderHeight);
  49. self.headerScrollView.frame = CGRectMake(leftHeaderWidth, 0, width - leftHeaderWidth, topheaderHeight);
  50. self.headerScrollView.contentSize = CGSizeMake( self.contentTableView.frame.size.width, self.headerScrollView.frame.size.height);
  51. self.contentTableView.frame = CGRectMake(0, 0, contentWidth + [self numberOfColumns] * [self columnMargin] , height - topheaderHeight);
  52. self.contentScrollView.frame = CGRectMake(leftHeaderWidth, topheaderHeight, width - leftHeaderWidth, height - topheaderHeight);
  53. self.contentScrollView.contentSize = self.contentTableView.frame.size;
  54. self.leftHeader.frame = CGRectMake(0, 0, [self leftHeaderWidth], [self topHeaderHeight]);
  55. }
  56. - (void)loadUI
  57. {
  58. [self loadHeaderScrollView];
  59. [self loadContentScrollView];
  60. [self loadLeftView];
  61. }
  62. - (void)reloadData
  63. {
  64. [self loadLeftViewData];
  65. [self loadContentData];
  66. [self loadHeaderData];
  67. }
  68. #pragma mark - UI
  69. - (void)loadHeaderScrollView
  70. {
  71. UIScrollView *headerScrollView = [[UIScrollView alloc] init];
  72. headerScrollView.delegate = self;
  73. self.headerScrollView = headerScrollView;
  74. self.headerScrollView.backgroundColor = [UIColor colorWithWhite:0.803 alpha:0.850];
  75. [self addSubview:headerScrollView];
  76. }
  77. - (void)loadContentScrollView
  78. {
  79. UIScrollView *scrollView = [[UIScrollView alloc] init];
  80. scrollView.bounces = NO;
  81. scrollView.delegate = self;
  82. UITableView *tableView = [[UITableView alloc] init];
  83. tableView.delegate = self;
  84. tableView.dataSource = self;
  85. tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
  86. [self addSubview:scrollView];
  87. [scrollView addSubview:tableView];
  88. self.contentScrollView = scrollView;
  89. self.contentTableView = tableView;
  90. }
  91. - (void)loadLeftView
  92. {
  93. UITableView *leftTableView = [[UITableView alloc] init];
  94. leftTableView.delegate = self;
  95. leftTableView.dataSource = self;
  96. leftTableView.separatorStyle = UITableViewCellSeparatorStyleNone;
  97. self.leftTableView = leftTableView;
  98. [self addSubview:leftTableView];
  99. UIView *leftHeader = [[UIView alloc] init];
  100. leftHeader.backgroundColor = [UIColor colorWithWhite:0.950 alpha:0.668];
  101. self.leftHeader = leftHeader;
  102. [self addSubview:leftHeader];
  103. }
  104. #pragma mark - Data
  105. - (void)loadHeaderData
  106. {
  107. NSArray *subviews = self.headerScrollView.subviews;
  108. for (UIView *subview in subviews) {
  109. [subview removeFromSuperview];
  110. }
  111. CGFloat x = 0.0;
  112. CGFloat w = 0.0;
  113. for (int i = 0; i < [self numberOfColumns] ; i++) {
  114. w = [self contentWidthForColumn:i] + [self columnMargin];
  115. FLEXTableColumnHeader *cell = [[FLEXTableColumnHeader alloc] initWithFrame:CGRectMake(x, 0, w, [self topHeaderHeight] - 1)];
  116. cell.label.text = [self columnTitleForColumn:i];
  117. [self.headerScrollView addSubview:cell];
  118. FLEXTableColumnHeaderSortType type = [self.sortStatusDict[[self columnTitleForColumn:i]] integerValue];
  119. [cell changeSortStatusWithType:type];
  120. UITapGestureRecognizer *gesture = [[UITapGestureRecognizer alloc] initWithTarget:self
  121. action:@selector(contentHeaderTap:)];
  122. [cell addGestureRecognizer:gesture];
  123. cell.userInteractionEnabled = YES;
  124. x = x + w;
  125. }
  126. }
  127. - (void)contentHeaderTap:(UIGestureRecognizer *)gesture
  128. {
  129. FLEXTableColumnHeader *header = (FLEXTableColumnHeader *)gesture.view;
  130. NSString *string = header.label.text;
  131. FLEXTableColumnHeaderSortType currentType = [self.sortStatusDict[string] integerValue];
  132. FLEXTableColumnHeaderSortType newType ;
  133. switch (currentType) {
  134. case FLEXTableColumnHeaderSortTypeNone:
  135. newType = FLEXTableColumnHeaderSortTypeAsc;
  136. break;
  137. case FLEXTableColumnHeaderSortTypeAsc:
  138. newType = FLEXTableColumnHeaderSortTypeDesc;
  139. break;
  140. case FLEXTableColumnHeaderSortTypeDesc:
  141. newType = FLEXTableColumnHeaderSortTypeAsc;
  142. break;
  143. }
  144. self.sortStatusDict = @{header.label.text : @(newType)};
  145. [header changeSortStatusWithType:newType];
  146. [self.delegate multiColumnTableView:self didTapHeaderWithText:string sortType:newType];
  147. }
  148. - (void)loadContentData
  149. {
  150. [self.contentTableView reloadData];
  151. }
  152. - (void)loadLeftViewData
  153. {
  154. [self.leftTableView reloadData];
  155. }
  156. - (UITableViewCell *)tableView:(UITableView *)tableView
  157. cellForRowAtIndexPath:(NSIndexPath *)indexPath
  158. {
  159. UIColor *backgroundColor = [UIColor whiteColor];
  160. if (indexPath.row % 2 != 0) {
  161. backgroundColor = [UIColor colorWithWhite:0.950 alpha:0.750];
  162. }
  163. if (tableView != self.leftTableView) {
  164. self.rowData = [self.dataSource contentAtRow:indexPath.row];
  165. FLEXTableContentCell *cell = [FLEXTableContentCell cellWithTableView:tableView
  166. columnNumber:[self numberOfColumns]];
  167. cell.contentView.backgroundColor = backgroundColor;
  168. cell.delegate = self;
  169. for (int i = 0 ; i < cell.labels.count; i++) {
  170. UILabel *label = cell.labels[i];
  171. label.textColor = [UIColor blackColor];
  172. NSString *content = [NSString stringWithFormat:@"%@",self.rowData[i]];
  173. if ([content isEqualToString:@"<null>"]) {
  174. label.textColor = [UIColor lightGrayColor];
  175. content = @"NULL";
  176. }
  177. label.text = content;
  178. label.backgroundColor = backgroundColor;
  179. }
  180. return cell;
  181. }
  182. else {
  183. FLEXTableLeftCell *cell = [FLEXTableLeftCell cellWithTableView:tableView];
  184. cell.contentView.backgroundColor = backgroundColor;
  185. cell.titlelabel.text = [self rowTitleForRow:indexPath.row];
  186. return cell;
  187. }
  188. }
  189. - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
  190. {
  191. return [self.dataSource numberOfRowsInTableView:self];
  192. }
  193. - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
  194. {
  195. return [self.dataSource multiColumnTableView:self heightForContentCellInRow:indexPath.row];
  196. }
  197. - (void)scrollViewDidScroll:(UIScrollView *)scrollView
  198. {
  199. if (scrollView == self.contentScrollView) {
  200. self.headerScrollView.contentOffset = scrollView.contentOffset;
  201. }
  202. else if (scrollView == self.headerScrollView) {
  203. self.contentScrollView.contentOffset = scrollView.contentOffset;
  204. }
  205. else if (scrollView == self.leftTableView) {
  206. self.contentTableView.contentOffset = scrollView.contentOffset;
  207. }
  208. else if (scrollView == self.contentTableView) {
  209. self.leftTableView.contentOffset = scrollView.contentOffset;
  210. }
  211. }
  212. #pragma mark -
  213. #pragma mark UITableView Delegate
  214. - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
  215. {
  216. if (tableView == self.leftTableView) {
  217. [self.contentTableView selectRowAtIndexPath:indexPath
  218. animated:NO
  219. scrollPosition:UITableViewScrollPositionNone];
  220. }
  221. else if (tableView == self.contentTableView) {
  222. [self.leftTableView selectRowAtIndexPath:indexPath
  223. animated:NO
  224. scrollPosition:UITableViewScrollPositionNone];
  225. }
  226. }
  227. #pragma mark -
  228. #pragma mark DataSource Accessor
  229. - (NSInteger)numberOfrows
  230. {
  231. return [self.dataSource numberOfRowsInTableView:self];
  232. }
  233. - (NSInteger)numberOfColumns
  234. {
  235. return [self.dataSource numberOfColumnsInTableView:self];
  236. }
  237. - (NSString *)columnTitleForColumn:(NSInteger)column
  238. {
  239. return [self.dataSource columnNameInColumn:column];
  240. }
  241. - (NSString *)rowTitleForRow:(NSInteger)row
  242. {
  243. return [self.dataSource rowNameInRow:row];
  244. }
  245. - (NSString *)contentAtColumn:(NSInteger)column row:(NSInteger)row;
  246. {
  247. return [self.dataSource contentAtColumn:column row:row];
  248. }
  249. - (CGFloat)contentWidthForColumn:(NSInteger)column
  250. {
  251. return [self.dataSource multiColumnTableView:self widthForContentCellInColumn:column];
  252. }
  253. - (CGFloat)contentHeightForRow:(NSInteger)row
  254. {
  255. return [self.dataSource multiColumnTableView:self heightForContentCellInRow:row];
  256. }
  257. - (CGFloat)topHeaderHeight
  258. {
  259. return [self.dataSource heightForTopHeaderInTableView:self];
  260. }
  261. - (CGFloat)leftHeaderWidth
  262. {
  263. return [self.dataSource widthForLeftHeaderInTableView:self];
  264. }
  265. - (CGFloat)columnMargin
  266. {
  267. return kColumnMargin;
  268. }
  269. - (void)tableContentCell:(FLEXTableContentCell *)tableView labelDidTapWithText:(NSString *)text
  270. {
  271. [self.delegate multiColumnTableView:self didTapLabelWithText:text];
  272. }
  273. @end