TUIChatFlexViewController.m 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. //
  2. // TUIChatFlexViewController.m
  3. // TUIChat
  4. //
  5. // Created by wyl on 2022/10/27.
  6. // Copyright © 2023 Tencent. All rights reserved.
  7. //
  8. #import "TUIChatFlexViewController.h"
  9. typedef enum : NSUInteger {
  10. FLEX_TOP,
  11. FLEX_Bottom,
  12. } FLEX_Location;
  13. CGFloat topMargin = NavBar_Height + 30;
  14. @interface TUIChatFlexViewController ()
  15. @property(nonatomic, assign) FLEX_Location currentLoaction;
  16. @property(nonatomic, strong) UIPanGestureRecognizer *panCover;
  17. @property(nonatomic, strong) UITapGestureRecognizer *singleTap;
  18. @end
  19. @implementation TUIChatFlexViewController
  20. - (void)viewDidLoad {
  21. [super viewDidLoad];
  22. self.view.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:.5];
  23. self.containerView.backgroundColor = [UIColor whiteColor];
  24. self.topImgView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:TUIChatImagePath_Minimalist(@"icon_flex_arrow")]];
  25. [self.topGestureView addSubview:self.topImgView];
  26. [self addSingleTapGesture];
  27. if (!_currentLoaction) {
  28. self.currentLoaction = FLEX_TOP;
  29. }
  30. [self updateSubContainerView];
  31. }
  32. - (void)addSingleTapGesture {
  33. // When clicking on the shadow, the page disappears
  34. self.view.userInteractionEnabled = YES;
  35. UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(singleTap:)];
  36. singleTap.cancelsTouchesInView = NO;
  37. [self.view addGestureRecognizer:singleTap];
  38. }
  39. - (void)singleTap:(UITapGestureRecognizer *)tap {
  40. CGPoint translation = [tap locationInView:self.containerView];
  41. if (translation.x < 0 || translation.y < 0) {
  42. [self dismissViewControllerAnimated:YES completion:nil];
  43. } else if (translation.x > self.containerView.frame.size.width || translation.y > self.containerView.frame.size.height) {
  44. [self dismissViewControllerAnimated:YES completion:nil];
  45. }
  46. }
  47. - (void)setnormalTop {
  48. self.currentLoaction = FLEX_TOP;
  49. }
  50. - (void)setNormalBottom {
  51. self.currentLoaction = FLEX_Bottom;
  52. }
  53. - (void)setCurrentLoaction:(FLEX_Location)currentLoaction {
  54. _currentLoaction = currentLoaction;
  55. if (currentLoaction == FLEX_TOP) {
  56. self.containerView.frame = CGRectMake(0, topMargin, self.view.frame.size.width, self.view.frame.size.height - topMargin);
  57. } else if (currentLoaction == FLEX_Bottom) {
  58. self.containerView.frame = CGRectMake(0, self.view.frame.size.height - kScale390(393), self.view.frame.size.width, kScale390(393));
  59. }
  60. }
  61. #pragma mark - lazy
  62. - (UIView *)containerView {
  63. if (_containerView == nil) {
  64. _containerView = [[UIView alloc] init];
  65. _containerView.layer.cornerRadius = kScale390(12);
  66. [self.view addSubview:_containerView];
  67. }
  68. return _containerView;
  69. }
  70. - (UIView *)topGestureView {
  71. if (_topGestureView == nil) {
  72. _topGestureView = [[UIView alloc] init];
  73. [_topGestureView addGestureRecognizer:self.panCover];
  74. [self.containerView addSubview:_topGestureView];
  75. }
  76. return _topGestureView;
  77. }
  78. - (UIPanGestureRecognizer *)panCover {
  79. if (_panCover == nil) {
  80. _panCover = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(onPanCover:)];
  81. }
  82. return _panCover;
  83. }
  84. - (void)onPanCover:(UIPanGestureRecognizer *)pan {
  85. CGPoint translation = [pan translationInView:self.topGestureView];
  86. CGFloat absX = fabs(translation.x);
  87. CGFloat absY = fabs(translation.y);
  88. if (MAX(absX, absY) < 2) return;
  89. if (absX > absY) {
  90. if (translation.x < 0) {
  91. // scroll left
  92. } else {
  93. // scroll right
  94. }
  95. } else if (absY > absX) {
  96. if (translation.y < 0) {
  97. // scroll up
  98. [self.topGestureView removeGestureRecognizer:self.panCover];
  99. [UIView animateWithDuration:0.3
  100. animations:^{
  101. self.currentLoaction = FLEX_TOP;
  102. [self.topGestureView addGestureRecognizer:self.panCover];
  103. }
  104. completion:^(BOOL finished) {
  105. if (finished) {
  106. [self updateSubContainerView];
  107. }
  108. }];
  109. } else {
  110. // scroll down
  111. if (self.currentLoaction == FLEX_Bottom) {
  112. [self dismissViewControllerAnimated:YES completion:nil];
  113. }
  114. [self.topGestureView removeGestureRecognizer:self.panCover];
  115. [UIView animateWithDuration:0.3
  116. animations:^{
  117. self.currentLoaction = FLEX_Bottom;
  118. [self.topGestureView addGestureRecognizer:self.panCover];
  119. }
  120. completion:^(BOOL finished) {
  121. if (finished) {
  122. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  123. [self updateSubContainerView];
  124. });
  125. }
  126. }];
  127. }
  128. }
  129. }
  130. - (void)updateSubContainerView {
  131. self.topGestureView.frame = CGRectMake(0, 0, self.containerView.frame.size.width, kScale390(40));
  132. self.topImgView.frame = CGRectMake((self.topGestureView.frame.size.width - kScale390(24)) * 0.5, kScale390(22), kScale390(24), kScale390(6));
  133. }
  134. @end