LKS_PerspectiveHierarchyView.m 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. //
  2. // LKS_PerspectiveHierarchyView.m
  3. // LookinServer
  4. //
  5. // Created by Li Kai on 2018/12/24.
  6. // https://lookin.work
  7. //
  8. #import "LKS_PerspectiveHierarchyView.h"
  9. #import "LKS_PerspectiveHierarchyCell.h"
  10. #import "LookinDisplayItem.h"
  11. #import "LookinServerDefines.h"
  12. @interface LKS_PerspectiveHierarchyView () <UITableViewDelegate, UITableViewDataSource>
  13. @property(nonatomic, strong) UIVisualEffectView *effectBgView;
  14. @property(nonatomic, strong) UIScrollView *scrollView;
  15. @property(nonatomic, strong) UITableView *tableView;
  16. @property(nonatomic, strong) LKS_PerspectiveDataSource *dataSource;
  17. @property(nonatomic, strong) CALayer *dragHintLayer;
  18. @property(nonatomic, assign) CGFloat currentMaxCellWidth;
  19. @property(nonatomic, weak) LKS_PerspectiveHierarchyCell *selectedCell;
  20. @end
  21. @implementation LKS_PerspectiveHierarchyView
  22. - (instancetype)initWithDataSource:(LKS_PerspectiveDataSource *)dataSource {
  23. if (self = [self initWithFrame:CGRectZero]) {
  24. self.dataSource = dataSource;
  25. self.dataSource.hierarchyView = self;
  26. self.clipsToBounds = YES;
  27. UIBlurEffect *effect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleDark];
  28. self.effectBgView = [[UIVisualEffectView alloc] initWithEffect:effect];
  29. [self addSubview:self.effectBgView];
  30. self.dragHintLayer = [CALayer layer];
  31. self.dragHintLayer.backgroundColor = LookinColorMake(70, 70, 70).CGColor;
  32. [self.dragHintLayer lookin_removeImplicitAnimations];
  33. [self.layer addSublayer:self.dragHintLayer];
  34. self.scrollView = [UIScrollView new];
  35. self.scrollView.bounces = YES;
  36. [self addSubview:self.scrollView];
  37. self.tableView = [[UITableView alloc] init];
  38. self.tableView.backgroundColor = [UIColor clearColor];
  39. #if TARGET_OS_TV
  40. #else
  41. self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
  42. #endif
  43. self.tableView.delegate = self;
  44. self.tableView.dataSource = self;
  45. [self.scrollView addSubview:self.tableView];
  46. // [self _updateCurrentMaxCellWidth];
  47. }
  48. return self;
  49. }
  50. - (void)layoutSubviews {
  51. [super layoutSubviews];
  52. self.effectBgView.frame = self.effectBgView.superview.bounds;
  53. // 留出一部分区域用来上下拖拽
  54. CGFloat dragAreaLength = 26;
  55. if (self.isHorizontalLayout) {
  56. self.dragHintLayer.frame = ({
  57. CGFloat width = 5;
  58. CGFloat height = 38;
  59. CGRectMake(self.layer.bounds.size.width - dragAreaLength / 2.0 - width / 2.0, self.layer.bounds.size.height / 2.0 - height / 2.0, width, height);
  60. });
  61. self.dragHintLayer.cornerRadius = self.dragHintLayer.bounds.size.width / 2.0;
  62. self.scrollView.frame = CGRectMake(0, 0, self.layer.bounds.size.width - dragAreaLength, self.layer.bounds.size.height);
  63. } else {
  64. self.dragHintLayer.frame = ({
  65. CGFloat width = 38;
  66. CGFloat height = 5;
  67. CGRectMake(self.layer.bounds.size.width / 2.0 - width / 2.0, dragAreaLength / 2.0 - height / 2.0, width, height);
  68. });
  69. self.dragHintLayer.cornerRadius = self.dragHintLayer.bounds.size.height / 2.0;
  70. self.scrollView.frame = CGRectMake(0, dragAreaLength, self.layer.bounds.size.width, self.layer.bounds.size.height - dragAreaLength);
  71. }
  72. CGSize tableSize = CGSizeMake(MAX(self.currentMaxCellWidth, self.scrollView.bounds.size.width), self.scrollView.bounds.size.height);
  73. self.scrollView.contentSize = tableSize;
  74. self.tableView.frame = CGRectMake(0, 0, tableSize.width, tableSize.height);
  75. }
  76. - (void)setIsHorizontalLayout:(BOOL)isHorizontalLayout {
  77. _isHorizontalLayout = isHorizontalLayout;
  78. if (isHorizontalLayout) {
  79. // 顶部给 menu 留一点位置
  80. self.tableView.contentInset = UIEdgeInsetsMake(40, 0, 0, 0);
  81. } else {
  82. self.tableView.contentInset = UIEdgeInsetsZero;
  83. }
  84. [self setNeedsLayout];
  85. }
  86. #pragma mark - UITableView
  87. - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
  88. return [self.dataSource numberOfRows];
  89. }
  90. - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
  91. LKS_PerspectiveHierarchyCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];
  92. if (!cell) {
  93. cell = [[LKS_PerspectiveHierarchyCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"cell"];
  94. cell.selectionStyle = UITableViewCellSelectionStyleNone;
  95. [cell.indicatorButton addTarget:self action:@selector(_handleCellExpansionButton:) forControlEvents:UIControlEventTouchUpInside];
  96. }
  97. LookinDisplayItem *item = [self.dataSource itemAtRow:indexPath.row];
  98. cell.displayItem = item;
  99. cell.indicatorButton.tag = indexPath.row;
  100. if (item.isSelected) {
  101. self.selectedCell = cell;
  102. }
  103. CGFloat cellWidth = [cell sizeThatFits:CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX)].width;
  104. if (self.currentMaxCellWidth < cellWidth) {
  105. self.currentMaxCellWidth = cellWidth;
  106. [self setNeedsLayout];
  107. }
  108. return cell;
  109. }
  110. - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
  111. return 26;
  112. }
  113. - (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section {
  114. return 0;
  115. }
  116. - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
  117. return 0;
  118. }
  119. - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
  120. LookinDisplayItem *item = [self.dataSource itemAtRow:indexPath.row];
  121. if (self.dataSource.selectedItem != item) {
  122. self.dataSource.selectedItem = item;
  123. }
  124. }
  125. #pragma mark - <LKS_PerspectiveDataSourceDelegate>
  126. - (void)dataSourceDidChangeDisplayItems:(LKS_PerspectiveDataSource *)dataSource {
  127. [self _tableViewReloadData];
  128. }
  129. - (void)dataSourceDidChangeSelectedItem:(LKS_PerspectiveDataSource *)dataSource {
  130. NSInteger row = [dataSource rowForItem:dataSource.selectedItem];
  131. NSIndexPath *indexPath = [NSIndexPath indexPathForRow:row inSection:0];
  132. [self.selectedCell reRender];
  133. if (!indexPath) {
  134. return;
  135. }
  136. // 去掉旧的 cell 的点击态
  137. [self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];
  138. NSArray<NSIndexPath *> *visibleIndexPaths = [self.tableView indexPathsForVisibleRows];
  139. if (![visibleIndexPaths containsObject:indexPath]) {
  140. [self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionMiddle animated:YES];
  141. }
  142. }
  143. #pragma mark - Others
  144. - (void)_tableViewReloadData {
  145. self.currentMaxCellWidth = 0;
  146. [self.tableView reloadData];
  147. }
  148. - (void)_handleCellExpansionButton:(UIButton *)button {
  149. NSUInteger row = button.tag;
  150. LookinDisplayItem *item = [self.dataSource itemAtRow:row];
  151. if (!item) {
  152. return;
  153. }
  154. if (!item.isExpandable) {
  155. return;
  156. }
  157. if (item.isExpanded) {
  158. [self.dataSource collapseItem:item];
  159. } else {
  160. [self.dataSource expandItem:item];
  161. }
  162. }
  163. @end