DSHPopupContainer.m 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. //
  2. // DSHPopupContainer.m
  3. // tetstst
  4. //
  5. // Created by 路 on 2018/11/8.
  6. // Copyright © 2018年 路. All rights reserved.
  7. //
  8. #import "DSHPopupContainer.h"
  9. #import <objc/runtime.h>
  10. @interface UIView (DSHCustomPopupView)
  11. @property (weak ,nonatomic) DSHPopupContainer *container;
  12. @end
  13. @implementation UIView (DSHCustomPopupView)
  14. - (void)setContainer:(DSHPopupContainer *)container {objc_setAssociatedObject(self, @selector(container), container, 0);}
  15. - (DSHPopupContainer *)container {return objc_getAssociatedObject(self, _cmd);}
  16. @end
  17. @interface _DSHContainerBackgroundView : UIControl
  18. @property (assign ,nonatomic) BOOL penetrable;
  19. @end
  20. @implementation _DSHContainerBackgroundView
  21. - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {UIView *view = [super hitTest:point withEvent:event]; if (_penetrable && view == self) return nil; return view;}
  22. @end
  23. @interface DSHPopupContainer ()
  24. @property (weak ,nonatomic ,readonly) UIView *containerView;
  25. @property (strong ,nonatomic) UIView <DSHCustomPopupView>*customPopupView;
  26. @property (strong ,nonatomic ,readonly) UIControl *backgroudControl;
  27. @end
  28. @implementation DSHPopupContainer
  29. + (DSHPopupContainer *)findContainerFromView:(UIView *)view; {
  30. return [self findContainersFromView:view].firstObject;
  31. }
  32. + (__kindof UIView <DSHCustomPopupView>*)findPopupViewFromView:(UIView *)view class:(Class)aClass; {
  33. return [self findPopupViewsFromView:view class:aClass].firstObject;
  34. }
  35. + (NSArray <DSHPopupContainer *>*)findContainersFromView:(UIView *)view; {
  36. if (view) {
  37. NSMutableArray *result = [NSMutableArray array];
  38. for (DSHPopupContainer *subview in view.subviews) {
  39. if ([subview isKindOfClass:[DSHPopupContainer class]]) {
  40. [result addObject:subview];
  41. }
  42. }
  43. return result;
  44. }
  45. return nil;
  46. }
  47. + (NSArray <__kindof UIView <DSHCustomPopupView>*>*)findPopupViewsFromView:(UIView *)view class:(Class)aClass; {
  48. if (view && aClass) {
  49. NSArray *array = [self findContainersFromView:view];
  50. if (array.count > 0) {
  51. NSMutableArray *result = [NSMutableArray array];
  52. for (DSHPopupContainer *container in array) {
  53. for (UIView *subview in container.subviews) {
  54. if ([subview conformsToProtocol:@protocol(DSHCustomPopupView)] && [subview isMemberOfClass:aClass]) {
  55. [result addObject:subview];
  56. }
  57. }
  58. }
  59. return result;
  60. }
  61. }
  62. return nil;
  63. }
  64. - (id)initWithCustomPopupView:(UIView<DSHCustomPopupView> *)customPopupView {
  65. return [self initWithCustomPopupView:customPopupView containerView:nil];
  66. }
  67. - (id)initWithCustomPopupView:(UIView <DSHCustomPopupView>*)customPopupView containerView:(UIView *)containerView; {
  68. if (![customPopupView isKindOfClass:[UIView class]]) return nil;
  69. self = [super initWithFrame:containerView.bounds];
  70. if (self) {
  71. self.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
  72. self.backgroundColor = nil;
  73. _containerView = containerView;
  74. if (!_containerView) {
  75. _containerView = [UIApplication sharedApplication].keyWindow;
  76. }
  77. _customPopupView = customPopupView;
  78. _customPopupView.container = self;
  79. _showAnimationDuration = .25;
  80. _dismissAnimationDuration = .25;
  81. _autoDismissWhenClickedBackground = YES;
  82. _maskColor = nil;
  83. _penetrable = NO;
  84. _backgroudControl = [[_DSHContainerBackgroundView alloc] init];
  85. _backgroudControl.autoresizingMask = self.autoresizingMask;
  86. _backgroudControl.frame = self.bounds;
  87. _backgroudControl.backgroundColor = _maskColor;
  88. [(_DSHContainerBackgroundView *)_backgroudControl setPenetrable:_penetrable];
  89. [_backgroudControl addTarget:self action:@selector(clickedBackgroudControl:) forControlEvents:UIControlEventTouchUpInside];
  90. [self addSubview:_backgroudControl];
  91. } return self;
  92. }
  93. - (void)show; {
  94. if (self.superview) {
  95. return;
  96. }
  97. self.frame = _containerView.bounds;
  98. CAKeyframeAnimation *anim = [CAKeyframeAnimation animationWithKeyPath:@"opacity"];
  99. anim.values = @[@(0) ,@(1)];
  100. anim.duration = _showAnimationDuration;
  101. [self.backgroudControl.layer addAnimation:anim forKey:nil];
  102. if ([_delegate respondsToSelector:@selector(popupContainer:willShowCustomView:)]) {
  103. [_delegate popupContainer:self willShowCustomView:_customPopupView];
  104. }
  105. [self addSubview:_customPopupView];
  106. if ([_customPopupView respondsToSelector:@selector(willPopupContainer:)]) {
  107. [_customPopupView willPopupContainer:self];
  108. }
  109. [_containerView addSubview:self];
  110. if ([_customPopupView respondsToSelector:@selector(didPopupContainer:duration:)]) {
  111. [_customPopupView didPopupContainer:self duration:_showAnimationDuration];
  112. }
  113. }
  114. - (void)dismiss; {
  115. if ([_delegate respondsToSelector:@selector(popupContainer:willDismissCustomView:)]) {
  116. [_delegate popupContainer:self willDismissCustomView:_customPopupView];
  117. }
  118. if ([_customPopupView respondsToSelector:@selector(willDismissContainer:duration:)]) {
  119. [_customPopupView willDismissContainer:self duration:_dismissAnimationDuration];
  120. }
  121. [UIView animateWithDuration:_dismissAnimationDuration animations:^{
  122. self.backgroudControl.alpha = 0;
  123. } completion:^(BOOL finished) {
  124. [self.customPopupView removeFromSuperview]; self.customPopupView = nil;
  125. [self removeFromSuperview];
  126. }];
  127. }
  128. - (void)clickedBackgroudControl:(id)sender {
  129. if (_autoDismissWhenClickedBackground) {
  130. [self dismiss];
  131. }
  132. }
  133. - (void)setMaskColor:(UIColor *)maskColor {
  134. _maskColor = maskColor;
  135. _backgroudControl.backgroundColor = _maskColor;
  136. }
  137. - (void)setBackgroundColor:(UIColor *)backgroundColor {
  138. if (!backgroundColor) {
  139. [super setBackgroundColor:backgroundColor];
  140. }
  141. self.maskColor = backgroundColor;
  142. }
  143. - (void)setPenetrable:(BOOL)penetrable {
  144. _penetrable = penetrable;
  145. ((_DSHContainerBackgroundView *)_backgroudControl).penetrable = _penetrable;
  146. }
  147. - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {UIView *view = [super hitTest:point withEvent:event]; if (_penetrable && view == self) return nil; return view;}
  148. @end