PopupView.m 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. //
  2. // PopupView.m
  3. // AIIM
  4. //
  5. // Created by qitewei on 2025/5/29.
  6. //
  7. #import "PopupView.h"
  8. @interface PopupView ()
  9. @property (nonatomic, strong) UIControl *backgroundControl;
  10. @property (nonatomic, weak) UIView *containerView;
  11. @property (nonatomic, assign) BOOL showing;
  12. @end
  13. @implementation PopupView
  14. - (instancetype)init {
  15. self = [super init];
  16. if (self) {
  17. [self commonInit];
  18. }
  19. return self;
  20. }
  21. - (instancetype)initWithFrame:(CGRect)frame {
  22. self = [super initWithFrame:frame];
  23. if (self) {
  24. [self commonInit];
  25. }
  26. return self;
  27. }
  28. - (void)commonInit {
  29. _position = PopupPositionCenter;
  30. _animationType = PopupAnimationTypeFromBottom;
  31. _dismissOnBackgroundTap = YES;
  32. _offset = 0;
  33. _containerType = PopupContainerTypeView;
  34. _backgroundColor = [UIColor colorWithWhite:0 alpha:0.5];
  35. _backgroundControl = [[UIControl alloc] init];
  36. _backgroundControl.backgroundColor = _backgroundColor;
  37. [_backgroundControl addTarget:self action:@selector(backgroundTapped) forControlEvents:UIControlEventTouchUpInside];
  38. [self addSubview:_backgroundControl];
  39. }
  40. - (void)layoutSubviews {
  41. [super layoutSubviews];
  42. _backgroundControl.frame = self.bounds;
  43. if (_customView) {
  44. CGRect frame = _customView.frame;
  45. switch (_position) {
  46. case PopupPositionTop:
  47. frame.origin.y = _offset;
  48. break;
  49. case PopupPositionCenter:
  50. frame.origin.y = (self.bounds.size.height - frame.size.height) / 2 + _offset;
  51. break;
  52. case PopupPositionBottom:
  53. frame.origin.y = self.bounds.size.height - frame.size.height + _offset;
  54. break;
  55. }
  56. frame.origin.x = (self.bounds.size.width - frame.size.width) / 2;
  57. _customView.frame = frame;
  58. }
  59. }
  60. #pragma mark - Public Methods
  61. - (void)showInView:(UIView *)view {
  62. if (_showing) return;
  63. // 确定容器视图
  64. if (_containerType == PopupContainerTypeWindow) {
  65. _containerView = [UIApplication sharedApplication].delegate.window;
  66. } else {
  67. _containerView = view;
  68. }
  69. if (!_containerView) {
  70. NSLog(@"Error: No container view available");
  71. return;
  72. }
  73. // 设置frame
  74. self.frame = _containerView.bounds;
  75. _backgroundControl.frame = self.bounds;
  76. _backgroundControl.backgroundColor = _backgroundColor;
  77. // 添加自定义视图
  78. if (_customView) {
  79. [self addSubview:_customView];
  80. [self setNeedsLayout];
  81. }
  82. // 添加到容器
  83. [_containerView addSubview:self];
  84. // 初始状态
  85. CGFloat startAlpha = 0;
  86. CGRect finalFrame = _customView.frame;
  87. CGRect startFrame = finalFrame;
  88. switch (_animationType) {
  89. case PopupAnimationTypeFromBottom:
  90. startFrame.origin.y = self.bounds.size.height;
  91. break;
  92. case PopupAnimationTypeFromTop:
  93. startFrame.origin.y = -startFrame.size.height;
  94. break;
  95. case PopupAnimationTypeFade:
  96. startAlpha = 0;
  97. break;
  98. }
  99. _customView.frame = startFrame;
  100. _customView.alpha = startAlpha;
  101. self.alpha = 0;
  102. // 执行动画
  103. [UIView animateWithDuration:0.3 animations:^{
  104. self.alpha = 1;
  105. self.customView.alpha = 1;
  106. self.customView.frame = finalFrame;
  107. } completion:^(BOOL finished) {
  108. self.showing = YES;
  109. }];
  110. }
  111. - (void)dismiss {
  112. if (!_showing) return;
  113. CGRect endFrame = _customView.frame;
  114. CGFloat endAlpha = 0;
  115. // 根据动画类型设置结束状态
  116. switch (_animationType) {
  117. case PopupAnimationTypeFromBottom:
  118. endFrame.origin.y = self.bounds.size.height;
  119. break;
  120. case PopupAnimationTypeFromTop:
  121. endFrame.origin.y = -endFrame.size.height;
  122. break;
  123. case PopupAnimationTypeFade:
  124. // 淡出只需要改变alpha
  125. break;
  126. }
  127. [UIView animateWithDuration:0.3 animations:^{
  128. if (self.animationType != PopupAnimationTypeFade) {
  129. self.customView.frame = endFrame;
  130. }else{
  131. self.customView.alpha = endAlpha;
  132. }
  133. self.alpha = 0;
  134. } completion:^(BOOL finished) {
  135. [self.customView removeFromSuperview];
  136. [self removeFromSuperview];
  137. self.showing = NO;
  138. if (self.dismissCompletion) {
  139. self.dismissCompletion();
  140. }
  141. }];
  142. }
  143. - (void)backgroundTapped {
  144. if (_dismissOnBackgroundTap) {
  145. [self dismiss];
  146. }
  147. }
  148. #pragma mark - Setters
  149. - (void)setCustomView:(UIView *)customView {
  150. if (_customView != customView) {
  151. [_customView removeFromSuperview];
  152. _customView = customView;
  153. [self addSubview:_customView];
  154. [self setNeedsLayout];
  155. }
  156. }
  157. - (void)setBackgroundColor:(UIColor *)backgroundColor {
  158. _backgroundColor = backgroundColor;
  159. _backgroundControl.backgroundColor = backgroundColor;
  160. }
  161. @end