LKS_PerspectiveHierarchyView.m 7.1 KB

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